16,466
社区成员
发帖
与我相关
我的任务
分享
// 重叠I/O处理线程
UINT _OverlappedThread(LPVOID lParam)
{
CServerSocket* pServer = (CServerSocket*)lParam;
while(bOverlapped) // 循环检测事件数组中的事件,并对接收的数据进行处理:)
{
DWORD dwIndex;
// 等候重叠I/O调用结束
// 因为我们把事件和Overlapped绑定在一起,重叠操作完成后我们会接到事件通知
dwIndex = WSAWaitForMultipleEvents(dwEventTotal,EventArray,FALSE,10,FALSE);
if(dwIndex == WSA_WAIT_TIMEOUT)
continue;
if(dwIndex == WSA_WAIT_FAILED) // 出现监听错误
{
int nErrorCode = WSAGetLastError();
if(nErrorCode == WSA_INVALID_HANDLE)
{
AfxMessageBox("监听出现错误:无效的 lphEvents 参数!"); // 代码经常会出现这种错误,我实在没时间改了,55555555
}
else
if(nErrorCode == WSA_INVALID_PARAMETER)
{
AfxMessageBox("监听出现错误:无效的 CEvents 参数!");
}
continue;
}
// 取得索引值,得知事件的索引号
dwIndex = dwIndex - WSA_WAIT_EVENT_0;
// 获得索引号以后,这个事件已经没有利用价值,重置之
WSAResetEvent(EventArray[dwIndex]);
// 然后确定当前索引号的SOCKET的重叠请求状态
DWORD dwBytesTransferred;
WSAOVERLAPPED& CurrentOverlapped = AcceptOverlapped[dwIndex]; // 这里纯粹为了减少代码长度,付给了一个临时变量
SOCKET& sockCurrent = sockAcceptArray[dwIndex] ; // 同上
WSAGetOverlappedResult(sockCurrent,¤tOverlapped ,
&dwBytesTransferred,FALSE,&Flags);
// 先检查通信对方是否已经关闭连接
// 如果==0则表示连接已经,则关闭套接字
if(dwBytesTransferred == 0)
{
CString strSock;
strSock.Format("SOCKET编号:%d",sockAcceptArray[dwIndex] );
::SendMessage(pServer->m_hNotifyWnd,WM_MSG_NEW_SOCKET,
(LPARAM)(LPCTSTR)strSock,(LPARAM)(LPCTSTR)"客户端断开连接!");
closesocket(sockCurrent);
sockCurrent = INVALID_SOCKET;
//WSACloseEvent( EventArray[dwIndex] );
dwEventTotal--;
if(dwEventTotal <= 0) // 如果没有事件等待则暂停重叠IO处理线程
{
pOverlappedThread->SuspendThread(); // 没有需要处理的重叠结构了,则本线程休眠
}
continue;
}
// DataBuf中包含接收到的数据,我们发到对话框中给予显示
CString strSock;
strSock.Format("SOCKET编号:%d",sockCurrent);
::SendMessage(pServer->m_hNotifyWnd,WM_MSG_NEW_MSG,
(LPARAM)(LPCTSTR)strSock,(LPARAM)(LPCTSTR)DataBuf[dwIndex].buf);
// 然后在套接字上投递另一个WSARecv请求(不要晕,注意看,代码和前面第一次WSARecv一样^_^)
Flags = 0;
ZeroMemory(¤tOverlapped,sizeof(WSAOVERLAPPED));
char buffer[DATA_BUFSIZE];
ZeroMemory(buffer,DATA_BUFSIZE);
CurrentOverlapped.hEvent = EventArray[dwIndex];
DataBuf[dwIndex].len = DATA_BUFSIZE;
DataBuf[dwIndex].buf = buffer;
// 开始另外一个WSARecv
if(WSARecv(sockCurrent,&DataBuf[dwIndex],1,&dwRecvBytes,&Flags,
¤tOverlapped ,NULL) == SOCKET_ERROR)
{
if(WSAGetLastError() != WSA_IO_PENDING)
{
AfxMessageBox("错误:投递Recv操作失败!!此套接字将被关闭!");
closesocket(sockCurrent);
sockCurrent = INVALID_SOCKET;
WSACloseEvent(EventArray[dwIndex]);
dwEventTotal--;
continue;
}
}
}
return 0;
}