我想写一个使用工作线程池和IO完成端口的服务器。服务器应该在多个客户端之间处理和转发消息。 '每客户端'数据在类ClientContext中。使用工作线程交换此类的实例之间的数据。我认为这是一个典型的情况。IO完成端口:WSARecv()如何工作?
但是,这些IO完成端口有两个问题。 (1)第一个问题是服务器基本上从客户端接收数据,但我不知道是否收到完整的消息。事实上,WSAGetLastError()总是返回WSARecv()仍然处于等待状态。我试图用WaitForMultipleObjects()等待事件OVERLAPPED.hEvent。但是,它永远阻塞,即WSARecv()从未在我的程序中完成。 我的目标是确保在进一步处理之前收到整个消息。我的消息头中有一个'消息长度'字段,但我真的不知道如何将它与IOCP函数参数一起使用。 (2)如果WSARecv()被注释掉在下面的代码片段中,程序仍然接收数据。那是什么意思?这是否意味着我根本不需要调用WSARecv()?我无法获得这些IO完成端口的确定性行为。 感谢您的帮助!
while(WaitForSingleObject(module_com->m_shutdown_event, 0)!= WAIT_OBJECT_0)
{
dequeue_result = GetQueuedCompletionStatus(module_com->m_h_io_completion_port,
&transfered_bytes,
(LPDWORD)&lp_completion_key,
&p_ol,
INFINITE);
if (lp_completion_key == NULL)
{
//Shutting down
break;
}
//Get client context
current_context = (ClientContext *)lp_completion_key;
//IOCP error
if(dequeue_result == FALSE)
{
//... do some error handling...
}
else
{
// 'per client' data
thread_state = current_context->GetState();
wsa_recv_buf = current_context->GetWSABUFPtr();
// 'per call' data
this_overlapped = current_context->GetOVERLAPPEDPtr();
}
while(thread_state != STATE_DONE)
{
switch(thread_state)
{
case STATE_INIT:
//Check if completion packet has been posted by internal function or by WSARecv(), WSASend()
if(transfered_bytes > 0)
{
dwFlags = 0;
transf_now = 0;
transf_result = WSARecv(current_context->GetSocket(),
wsa_recv_buf,
1,
&transf_now,
&dwFlags,
this_overlapped,
NULL);
if (SOCKET_ERROR == transf_result && WSAGetLastError() != WSA_IO_PENDING)
{
//...error handling...
break;
}
// put received message into a message queue
}
else // (transfered_bytes == 0)
{
// Another context passed data to this context
// and notified it via PostQueuedCompletionStatus().
}
break;
}
}
}