【问题标题】:GetQueuedCompletionStatus blocks foreverGetQueuedCompletionStatus 永远阻塞
【发布时间】:2014-09-28 00:04:29
【问题描述】:

我正在编写一个服务器应用程序并且我想使用 IOCompletion 端口,所以我为服务器编写了一个原型,但是我遇到了 GetQueuedCompletionStatus 的问题,它永远不会返回(它阻塞)。下面是我的代码:

bool CreateSocketOverlappedServer()
{
  WSADATA wsaData;
  SOCKADDR_IN sockaddr;

  if(WSAStartup(MAKEWORD(2,2,),&wsaData)){
    _tprintf(_T("Unable to start up\n"));
    return false;
  }

  SrvSocket = WSASocket(AF_INET,SOCK_STREAM,0,NULL,NULL,WSA_FLAG_OVERLAPPED);
  if(SrvSocket==INVALID_SOCKET){
    _tprintf(_T("Unable to start socket\n"));
    return false;
  }

  sockaddr.sin_family = AF_INET;
  sockaddr.sin_port = htons(10000);
  sockaddr.sin_addr.s_addr = INADDR_ANY;

  /* now bind the socket */
  if(bind(SrvSocket, (SOCKADDR *)&sockaddr, sizeof(SOCKADDR_IN))==SOCKET_ERROR){
    _tprintf(_T("Unable to bind socket\n"));
    return false;
  }

  if(listen(SrvSocket, 5)==SOCKET_ERROR){
    _tprintf(_T("Error listening\n"));
    return false;
  }

  return true;
}

void WorkerThread(void *arg)
{
   bool bret= false;
   DWORD dwTransferedBytes=0;
   CLIENTS *client;
   PPER_IO_OPERATION_DATA data;

   /* Just sleep for now */
   while(true){
     _tprintf(_T("Entering while\n"));
     bret = GetQueuedCompletionStatus(hIocp,&dwTransferedBytes,(PULONG_PTR)&client,(LPOVERLAPPED *) &data,INFINITE);
     if(!bret){
       _tprintf(_T("Unable to process completion port\n"));
     }
   }
   //Sleep(10000); 
}

void AcceptClientConnections(void *arg)
{
  套接字客户端套接字;
  客户 *c;

  _tprintf(_T("开始接受客户端连接\n"));


  而(真){
    ClientSocket = 接受(SrvSocket, NULL,NULL);

    如果(ClientSocket==INVALID_SOCKET){
      _tprintf(_T("无法接受连接\n"));
      继续;
    }

    /* 与完成端口关联 */
    c = (CLIENTS *)malloc(sizeof(CLIENTS));
    c->sock = ClientSocket;

    /* 关联完成端口 */
    if(!CreateIoCompletionPort((HANDLE)ClientSocket, hIocp, (ULONG_PTR)c,0)){
      _tprintf(_T("无法关联完成端口\n: %d"),GetLastError());

    }

  }
}

有什么想法吗? 提前致谢。

【问题讨论】:

    标签: sockets io-completion-ports


    【解决方案1】:

    您没有正确使用完成端口,因此它与任何事情无关,因此没有要报告的状态。使用带有套接字的完成端口是一个两步过程,但您只完成了一半的步骤。

    阅读以下 MSDN 文章了解详细信息:

    Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports

    【讨论】:

    • 您可能还想查看我的免费 IOCP 客户端/服务器框架,该框架显示了比 MSDN 样本更高级的 IOCP 用法,并且希望在您的原型中更容易重用:@987654322 @
    • Remy,请澄清一下,我创建了一个 Iocompletion 端口,例如:hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL,0,0,),然后在我的线程池中将每个接受的套接字与该完成端口相关联, GetQueuedCompletionStatus 被调用,但我面临的是它永远不会返回,我的意思是它永远阻塞,我通过 telnet 连接到服务器并发送任何字符串,但 GetQueuedCompletionstatus 阻塞。有什么建议吗?
    • 您没有在发布的代码中显示最初的CreateIoCompletionPort() 调用,也没有显示任何在连接后使用套接字的代码。例如,您是否使用 WSAOVERLAPPED 结构调用 WSARecv() 以开始通过重叠 I/O 从接受的套接字读取?您需要这样做才能为入站数据触发 GetQueuedCompletionStatus()
    • 对不起,因为我没有显示对 CreateIocompletionport 的调用,但是对 WSARecv 的调用是在 GetQueuedCompletionStatus 之后进行的,对吧?
    • 不,您必须在accept() 为客户端返回一个新的套接字句柄后调用WSARecv()GetQueuedCompletionStatus() 无法报告尚未排队的事物的状态。您使用WSARecv() 将重叠读取排队,然后GetQueuedCompletionStatus() 报告读取实际上从客户端接收到一些数据,然后您发出另一个WSARecv() 以排队另一个读取操作,依此类推。发送数据也是一样。使用WSASend() 排队发送操作,然后GetQueuedCompletionStatus() 报告发送何时完成。
    【解决方案2】:

    一种可能性:检查您是否已将侦听器套接字与完成端口相关联(我自己犯了这个错误)。如果你没有 GetQueuedCompletionStatus() 将永远阻塞。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-24
      • 1970-01-01
      相关资源
      最近更新 更多