我目前正在尝试一些用于套接字编程的新库(IOCP)。而且我偶然发现了AcceptEx功能来启用异步连接。

如文档所述:



但是,当客户端连接时,我不会获得任何完成。但是,当客户端发送数据时,我确实完成了操作。

这是我的代码:

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;
    }
}

有什么建议可以接收完成?

编辑:
我在m_lpfnAcceptEx()之后将hSocket绑定(bind)到完成端口

最佳答案

首先,当完成完成时,您在对WSAOVERLAPPED的调用上方要在堆栈上声明的AcceptEx()和数据缓冲区将不存在(除非您在同一函数中调用GetQueuedCompletionStatus(),这有点小怪异)。您需要动态分配它们或将它们合并。

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

  • 创建一个设置了WSA_FLAG_OVERLAPPED的套接字。
  • 绑定(bind)到您想收听的地址。
  • 调用您希望的积压进行监听。
  • 使用监听套接字和对AcceptEx()的调用来动态加载WSAIoctl(并非绝对必要,并且您显示的代码应该可以工作,但是通过这种方式,您可以确保从同一基础winsock提供程序获取监听套接字,并且它支持AcceptEx()。
  • 加载GetAcceptExSockaddrs()的方式与加载AcceptEx()的方式相同-接受完成后将需要它。
  • 将监听套接字与IOCP关联。

  • 现在,您可以使用监听套接字和新创建的“accept”套接字发布许多AcceptEx()调用,如下所示:
  • 创建一个设置了WSA_FLAG_OVERLAPPED的套接字。
  • 将套接字与IOCP关联。

  • 如上所述,您需要确保每个调用的缓冲区和OVERLAPPED都是唯一的,并且持续到完成为止。

    完成时,您必须执行以下操作。
  • 使用监听套接字作为数据,在接受的套接字上使用setsockopt()调用SO_UPDATE_ACCEPT_CONTEXT ...
  • 使用GetAcceptExSockaddrs()阻止您的地址。
  • 处理任何数据(如果您在缓冲区中为数据分配了足够的空间)。

  • 请注意,根据设计,AcceptEx()可用于接受新连接并通过一次操作从该连接返回初始数据(在您知道在开始做事之前总是需要一些数据的情况下,这会导致性能略有提高,但是如果要防御拒绝服务攻击,这非常复杂,只需通过连接而不发送数据就可以发起拒绝服务攻击-我写了有关here的文章。

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

    请注意,马丁·詹姆斯(Martin James)对您问题的最初评论实际上是您正在寻找的答案。不要传递outBufLen - ((sizeof (sockaddr_in) + 16) * 2),传递0

    关于c++ - IOCP AcceptEx在连接时未创建完成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19956186/

    10-10 05:07