一、定义结构
typedef struct PER_HANDLE_DATA
{
SOCKET s;
SOCKADDR_IN RemoteAddr;
}*PPER_HANDLE_DATA;
typedef struct PER_IO_DATA
{
WSAOVERLAPPED ol;
char buf[12];
#define OP_READ 1
#define OP_WRITE 2
int nOperation;
}*PPER_IO_DATA;
二、创建一个完成端口
HANDLE hCompletion=CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0);
三、创建合适的工作线程
SYSTEM_INFO si;
GetSystemInfo(&si);
for(int i=0;i<si.dwNumberOfProcessors*2;++i)//如果需要使用WaitForSingleObject之类使线程等待,避免CPU空闲
CreateThread(NULL,0,WorkThread,(LPVOID)hCompletion,0,0);
四、绑定监听socket
SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);
SOCKADDR_IN srvaddr;
srvaddr.sin_addr.S_un.S_addr=INADDR_ANY;
srvaddr.sin_family=AF_INET;
srvaddr.sin_port=htons(4567);
bind(s,(SOCKADRR*)&srvaddr,sizeof srvaddr);
listen(s,5);
五、处理客户连接
while(1)
{
SOCKADDR_IN Remoteaddr;
int nlen=sizeof Remoteaddr;
SOCKET sAccept=accept(sListen,(SOCKADDR*)Remoteaddr,&nlen);
PPER_HANDLE_DATA pPerHandle=(PER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
pPerHandle->s=sAccept;
memcpy(&pPerHandle->RemoteAddr,Remoteaddr,nlen);
CreateIoCompletionPort((HANDLE)pPerHandle->s,hCompletion,(DWORD)perHandle,0);//关联per数据
PPER_IO_DATA pPerIO=(PER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
pPerIO->nOperation=OP_READ;
WSABUF buf;
buf.buf=pPerIO->buf;
buf.len=12;
DWORD dwRecv;
DWORD dwFlags=0;
WSARecv(pPerHandle->s,&buf,1,&dwRecv,&dwFlags,&pPerIO->ol,NULL);//投递第一个请求
}
六、处理客户请求(工作线程)
HANDLE hCompletion=(HANDLE)lpParam;
DWORD dwTrans;
PPER_HANDLE_DATA pPerHandle;
PPER_IO_DATA pPerIO;
while(1)
{
bool ok=GetQueuedCompletionStatus(hCompletion,&dwTrans,(PULONG_PTR)&pPerHandle,(LPOVERLAPPED*)&pPerIO,WSA_INFINITE);//查看是否有异步IO请求完成 完成返回
if(!bok)//出错了
{
closesocket(pPerHandle->s);
GlobalFree(pPerHandle);
GlobalFree(pPerIO);
continue;
}
if(dwTrans==0&&(pPerIO->nOperation==OP_READ||pPerIO->nOperation==OP_WRITE))//连接关闭了
{
closesocket(pPerHandle->s);
GlobalFree(pPerHandle);
GlobalFree(pPerIO);
continue;
}
switch(pPerIO->nOperation)
{
case OP_READ:
pPerIO->buf[dwTrans]='/0';
printf(pPerIO->buf);
WSABUF buf;
buf.buf=pPerIO->buf;
buf.len=12;
pPerIO->nOperation=OP_READ;
DWORD nFlags=0;
WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL);//继续投递
break;
case OP_WRITE:
case OP_ACCEPT:
break;
}
}