这是在学《Windows网络编程(第二版)》第六章时制作的一个例子由于书中没有给出简洁的例子,本人在学这里时就费了很多时间。 现在把完成的代码贴出来,供大家参考。 本程序在VS2003编译器编译运行。在6.0下可能需要稍加修改。
DWORD WINAPI ServerThread(LPVOID lpParam) { HANDLE CompletionPort = (HANDLE)lpParam; DWORD bytes; LPPER_HANDLE_DATA perHandleData = NULL; //单句柄数据 LPPER_IO_DATA perIoData; //单IO数据 DWORD Flags; int ret; DWORD RecvBytes; //进入循环的等待重叠操作的完成 while(true) { bytes = -1; ret=GetQueuedCompletionStatus( CompletionPort, //原先的完成端口句柄 &bytes, //重叠操作完成的字节数 (LPDWORD)&perHandleData, //原先和完成端口句柄关联起来的单句柄数据 (LPOVERLAPPED*)&perIoData, //用于接收已完成的IO操作的重叠结构 INFINITE); //在完成端口上等待的时间 INFINITE 为无限等待
//先检查在套接字上是否发生错误 //当发生错误时关闭套接字同时释放掉所有的内存. int i = 0; if(bytes == 0 && (perIoData->operatorType == RECV || perIoData->operatorType == SEND)) { closesocket(perHandleData->socket); GlobalFree(perHandleData); GlobalFree(perIoData); cout<<"closesocket and globalfree perhandledata periodata!"<<endl; continue; } //这是AcceptEx函数处理完成,在下面处理 if(perIoData->operatorType == ACCEPT) //处理连接操作 { //使用GetAcceptExSockaddrs函数 获得具体的各个地址参数. if(setsockopt( perIoData->client, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, ( char* )&(perHandleData->socket ), sizeof( perHandleData->socket ) )==SOCKET_ERROR) cout<<"setsockopt..."<<endl;
perHandleData->socket = perIoData->client;
//memcpy(&(perHandleData->clientAddr),raddr,sizeof(raddr)); //将新的客户套接字与完成端口连接 CreateIoCompletionPort((HANDLE)perHandleData->socket, CompletionPort,(ULONG_PTR)perHandleData,0);
memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED)); perIoData->operatorType = RECV; //将状态设置成接收 //设置WSABUF结构 perIoData->buffer.buf = perIoData->dataBuffer; perIoData->buffer.len = perIoData->dataLength = DATA_LENGTH;
cout<<"wait for data arrive(Accept)..."<<endl; Flags = 0; if(WSARecv(perHandleData->socket,&(perIoData->buffer),1, &RecvBytes,&Flags,&(perIoData->overlapped),NULL)==SOCKET_ERROR) if(WSAGetLastError()==WSA_IO_PENDING) cout<<"WSARecv Pending..."<<endl; continue; } if(perIoData->operatorType == RECV) cout<<perIoData->buffer.buf<<endl; //将接收到的数据显示出来 Flags = 0; perIoData->operatorType = RECV; //设置成接受数据类型
ZeroMemory(&(perIoData->overlapped),sizeof(OVERLAPPED)); //重新投递一个新的接收请求 cout<<" wait for data arrive..."<<endl; WSARecv(perHandleData->socket,&(perIoData->buffer),1, &RecvBytes,&Flags,&(perIoData->overlapped),NULL); }
return 0; } 在前面有贴出了一个简单的客户端例子,可以结合起来调试,很方便的。 欢迎同道同志来信讨论 chang841018@yahoo.com.cn
(iwgh) |