IOCP AcceptEx不会在连接时创build完成

我目前正在尝试一些新的库(IOCP)进行套接字编程。 我偶然发现了AcceptExfunction来启用asynchronous连接。

正如文档所述:

与accept函数不同,AcceptEx函数使用重叠的I / O。 如果您的应用程序使用AcceptEx,它可以为相对较less的线程数量的大量客户端提供服务。 与所有重叠的Windows函数一样,可以使用Windows事件或完成端口作为完成通知机制。

但是,当客户端连接时,我不会完成任何完成。 当客户端发送数据时,我会完成。

这是我的代码:

DWORD dwBytes; GUID GuidAcceptEx = WSAID_ACCEPTEX; int iResult = WSAIoctl(m_hSocket, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof (GuidAcceptEx), &m_lpfnAcceptEx, sizeof (m_lpfnAcceptEx), &dwBytes, NULL, NULL); if (iResult == SOCKET_ERROR) { CloseSocket(); } 

接着:

 WSAOVERLAPPED olOverlap; memset(&olOverlap, 0, sizeof (olOverlap)); char lpOutputBuf[1024]; int outBufLen = 1024; DWORD dwBytes; BOOL bRet = m_lpfnAcceptEx( m_hSocket, hSocket, lpOutputBuf, outBufLen - ((sizeof (sockaddr_in) + 16) * 2), sizeof (sockaddr_in) + 16, sizeof (sockaddr_in) + 16, &dwBytes, &olOverlap); if ( bRet == FALSE ) { DWORD dwRet = WSAGetLastError(); if( dwRet != WSA_IO_PENDING ) { return dwRet; } } 

任何build议如何接收完成?

编辑:我将hSocket绑定到completionport后m_lpfnAcceptEx()

Solutions Collecting From Web of "IOCP AcceptEx不会在连接时创build完成"

首先,当你在调用AcceptEx()时候,声明在栈上的WSAOVERLAPPED和数据缓冲区在完成时不会存在(除非你在相同的函数中调用GetQueuedCompletionStatus() ,这将是一件奇怪的事情) 。 您需要动态分配或汇集它们。

其次,在调用AcceptEx()之后,您声明将套接字关联到完成端口。 那是错的 在调用AcceptEx()之前,您需要做这些事情。

  1. 创建一个设置了WSA_FLAG_OVERLAPPED的套接字。
  2. 把它绑定到你想听的地址。
  3. 打电话来听你想要的积压。
  4. 使用监听套接字和对WSAIoctl的调用来动态加载AcceptEx() (不是绝对必要的,并且您显示的代码应该可以工作,但是这样可以确保从相同的底层winsock提供程序中获取监听套接字,并且它支持AcceptEx() 。
  5. 以与加载AcceptEx()相同的方式加载GetAcceptExSockaddrs() – 一旦接受完成,您将需要它。
  6. 将监听套接字与您的IOCP相关联。

现在,您可以使用侦听套接字和新创建的“accept”套接字来发布一些AcceptEx()调用,如下所示:

  1. 创建一个设置了WSA_FLAG_OVERLAPPED的套接字。
  2. 将套接字关联到您的IOCP。

如上所述,您需要确保每次调用缓冲区和OVERLAPPED都是唯一的,并且直到完成发生。

当完成发生时,您必须执行以下操作….

  1. 使用侦听套接字作为数据,在接受的套接字上使用SO_UPDATE_ACCEPT_CONTEXT调用setsockopt()
  2. 使用GetAcceptExSockaddrs()解锁您的地址。
  3. 处理任何数据(如果在缓冲区中为数据分配了足够的空间)。

请注意,通过设计AcceptEx()可以用来接受一个新的连接,并在一个操作中返回来自该连接的初始数据(这会导致稍微好一点的性能,如果你知道在开始做事之前总是需要一些数据但是如果你想要防御拒绝服务攻击,可以简单地通过连接而不是发送数据来启动,但是管理非常复杂 – 我在这里写了这个)。

如果您不希望AcceptEx()等待数据到达,那么只需提供一个足够大的数据缓冲区,以便返回地址并将0作为“缓冲区大小”传递。 这将导致AcceptEx()像重叠的accept()一样操作并在建立连接后立即返回。

请注意,Martin James对你的问题的最初评论其实就是你正在寻找的答案。 不要传出outBufLen - ((sizeof (sockaddr_in) + 16) * 2) ,传递0