我正在编写使用IO完成端口的多线程客户端。多线程IOCP客户端问题
我创建并连接了具有WSA_FLAG_OVERLAPPED属性集的套接字。
if ((m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
throw std::exception("Failed to create socket.");
}
if (WSAConnectByName(m_socket, L"server.com", L"80", &localAddressLength, reinterpret_cast<sockaddr*>(&localAddress), &remoteAddressLength, &remoteAddress, NULL, NULL) == FALSE)
{
throw std::exception("Failed to connect.");
}
我的IO完成端口与插座关联。
if ((m_hIOCP = CreateIoCompletionPort(reinterpret_cast<HANDLE>(m_socket), m_hIOCP, NULL, 8)) == NULL)
{
throw std::exception("Failed to create IOCP object.");
}
在我尝试通过套接字发送一些数据之前,所有内容似乎都很顺利。
SocketData* socketData = new SocketData;
socketData->hEvent = 0;
DWORD bytesSent = 0;
if (WSASend(m_socket, socketData->SetBuffer(socketData->GenerateLoginRequestHeader()), 1, &bytesSent, NULL, reinterpret_cast<OVERLAPPED*>(socketData), NULL) == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
throw std::exception("Failed to send data.");
}
WSASend不会返回SOCKET_ERROR,而是将上一个错误设置为WSA_IO_PENDING,WSASend会立即返回。
我需要IO挂起,并完成处理我的线程函数,这也是我的工作线程。
unsigned int __stdcall MyClass::WorkerThread(void* lpThis)
{
}
我之前已经这样做了,但我不知道什么是在这种情况下会错了,我会非常感谢帮助我解决这个问题的任何努力。
那么问题是,WSARecv立即返回,而不是张贴到IOCP队列。返回的最后一个错误是0,因为它应该是ERROR_IO_PENDING。我通过使用ConnectEx而不是WSAConnect解决了问题。感谢您的回复:) – Carl 2010-06-14 10:42:31
我的观点是,WSARecv CAN LEGALLY返回0,IT STILL以与返回ERROR_IO_PENDING时相同的方式发布IO完成,除非您通过调用SetFleCompletionNotificationModes()来调整它的工作方式你告诉它不要在它返回成功时发布一个IO完成......如果你已经用适当的标志调用SetFileCompletionNotificationModes(),你只需要有成功返回的特殊情况代码。 – 2010-06-14 12:51:16
啊,我不知道。好的,谢谢你! =] – Carl 2010-06-14 20:46:04