18,356
社区成员
发帖
与我相关
我的任务
分享
//服务器接收线程函数定义
DWORD WINAPI AcceptThread(LPVOID lpParam)
{
CServer *pServer = (CServer*) lpParam;
sockaddr_in addrClient;
INT addrLen = sizeof(addrClient);
SOCKET ClientSocket;
while(TRUE)
{
ClientSocket = accept(pServer->m_ServerSocket,(SOCKADDR*)&addrClient,&addrLen);
if (ClientSocket == INVALID_SOCKET)
continue;
//创建工作者线程
pServer->UserSessionThread(ClientSocket);
//开辟内存区
PPER_HANDLE_DATA pPerHandle =
(PPER_HANDLE_DATA)::GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
pPerHandle->socket = ClientSocket;
memcpy(&pPerHandle->addr,&addrClient,addrLen);
//关联完全端口
CreateIoCompletionPort((PPER_HANDLE_DATA)pPerHandle->socket,
pServer->m_hCompletionPort,(DWORD)pPerHandle,0);
//投递第一个Recv请求
PPER_IO_DATA pPerIO = (PPER_IO_DATA)::GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
pPerIO->OperatorType = IO_RECV;
WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
//接收操作字节数的指针
DWORD dwRecv;
//指向标志位的指针
DWORD dwFlags = 0;
::WSARecv(pPerHandle->socket,&buf,1,&dwRecv,&dwFlags,&pPerIO->ol,NULL);
}
closesocket(ClientSocket);
return 1;
}
DWORD WINAPI CompletionThread(LPVOID lpParam)
{
CServer *pServer = (CServer*) lpParam;
//传输字节数
DWORD dwTrans;
PPER_HANDLE_DATA pPerHandle;
PPER_IO_DATA pPerIO;
while(TRUE)
{
BOOL bRect = ::GetQueuedCompletionStatus(pServer->m_hCompletionPort,
&dwTrans, //一次I/O操作,接收实际传输的字节数
(LPDWORD)&pPerHandle, //单据柄数据
(LPOVERLAPPED*)&pPerIO,
WSA_INFINITE);
if(!bRect)
{//在此套接字有错误发生
::closesocket(pPerHandle->socket);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}
if ( 0 == dwTrans &&
(pPerIO->OperatorType == IO_RECV ||pPerIO->OperatorType == IO_SEND))
{//套接字被对方关闭
::closesocket(pPerHandle->socket);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}
switch(pPerIO->OperatorType)
{
case IO_RECV: //完成一个接收请求
{
//继续接收
WSABUF buf;
buf.buf = pPerIO->buf;
buf.len = BUFFER_SIZE;
pPerIO->OperatorType = IO_RECV;
DWORD dwFlags = 0;
//投递一个Recv请求
::WSARecv(pPerHandle->socket,&buf,1,&dwTrans,&dwFlags,&pPerIO->ol,NULL);
}
break;
case IO_SEND: //完成一个发送请求
{
//省略代码
//参数也省略了
//投递一个发送请求
pPerIO->OperatorType = IO_SEND;
dwError=WSASend(m_hClientSocket......);
}
;
break;
case IO_END: //完成一个结束请求
;
break;
default :
;
}
}
return 1;
}
typedef struct _PER_IO_DATA //单IO数据
{
OVERLAPPED ol; //重叠结构 必须在第一个字段
CHAR buf[BUFFER_SIZE]; //数据缓冲区
INT OperatorType; //操作类型
}PER_IO_DATA,*PPER_IO_DATA;
typedef struct _PER_HANDLE_DATA //单句柄数据
{
SOCKET socket; //对应的套接字
sockaddr_in addr; //客户端地址
}PER_HANDLE_DATA,*PPER_HANDLE_DATA;
typedef struct _PER_IO_DATA //单IO数据
{
OVERLAPPED ol; //重叠结构 必须在第一个字段
CHAR buf[BUFFER_SIZE]; //数据缓冲区
INT OperatorType; //操作类型
}PER_IO_DATA,*PPER_IO_DATA;