上篇说到IOCP的精简实现,这篇来讲IOCP客户端和消息传递
在ConnectEx代码之前,CreateIoCompletionPort的第三个参数,把socket句柄+0x01000000作为传递
sNew = ::WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); if (sNew != SOCKET_ERROR) { ::CreateIoCompletionPort((HANDLE)sNew, hCompletion, (DWORD)sNew+0x01000000, 0); ::bind(sNew, (sockaddr*)&Local, sizeof(Local)); if (ConnectEx(sNew, (PSOCKADDR)&SSer, sizeof(SSer), NULL, 0, &dwRecv, &over) == FALSE) { if (::WSAGetLastError() != ERROR_IO_PENDING) { printf("ConnectEx failed with error [%d] ", ::WSAGetLastError()); } } }
工作线程接收到,ConnectEx异步处理结果时,通过GetQueuedCompletionStatus接收第三个参数,做响应的处理即可
char *cTmp = (char*)&SSoc; ::GetQueuedCompletionStatus(hCompletion, &dTmp,(LPDWORD)&SSoc, &OverLapped, WSA_INFINITE); switch (cTmp[3]) { case 0x01: { cTmp[3] = 0; .....处理 } break; }
后续WSASend、WSARecv等可以使用PostQueuedCompletionStatus方式调用即可,当然消息可以自定义,CON:0x01、Send:0x02,Recv:0x03、closesocket:0x04等等,要注意后面要补齐6个0,这样就实现了SOCKET句柄带消息类型传递。
PostQueuedCompletionStatus(hCompletion, DWORD(0), (DWORD)sNew+0x01000000, NULL);
甚至还可以用WSAAsyncSelect这货的PostThreadMessage传递MSG,用之前要修改注册表设置最大消息上限。
Windows Registry Editor Version 5.00
;增加消息上限
[HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionWindows]
"USERPostMessageLimit"=dword:000FFFFF