Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ IOCP AcceptEx在连接时未创建完成_C++_Windows_Winsock_Iocp - Fatal编程技术网

C++ IOCP AcceptEx在连接时未创建完成

C++ IOCP AcceptEx在连接时未创建完成,c++,windows,winsock,iocp,C++,Windows,Winsock,Iocp,我目前正在尝试一些用于套接字编程的新库(IOCP)。我偶然发现了启用异步连接的功能 正如文件所说: 与accept函数不同,AcceptEx函数使用重叠的I/O。如果您的应用程序使用AcceptEx,它可以使用相对较少的线程为大量客户机提供服务。与所有重叠的Windows功能一样,Windows事件或完成端口都可以用作完成通知机制 但当客户连接时,我没有收到任何完成。然而,当客户端发送数据时,我确实得到了一个完成 这是我的代码: DWORD dwBytes; GUID GuidAcceptEx

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

正如文件所说:

与accept函数不同,AcceptEx函数使用重叠的I/O。如果您的应用程序使用AcceptEx,它可以使用相对较少的线程为大量客户机提供服务。与所有重叠的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;
    }
}
有没有关于如何接收完工通知的建议

编辑:
我在m_lpfnaptex()之后将hSocket绑定到completionport()

首先,在调用
AcceptEx()
的堆栈上声明的
wsaooverlapped
和数据缓冲区在完成时将不存在(除非调用
GetQueuedCompletionStatus())
在同一个函数中,这有点奇怪)。您需要动态地分配或汇集它们

其次,您声明在调用
AcceptEx()
后将套接字与完成端口相关联。那是错误的。在调用
AcceptEx()
之前,需要执行这些操作

  • 创建一个设置有重叠的WSA\u标志的套接字
  • 将其绑定到您要侦听的地址
  • 用你想要的待办事项调用listen
  • 使用侦听套接字动态加载
    AcceptEx()
    ,并调用
    WSAIoctl
    (严格来说不是必需的,您显示的代码应该可以工作,但通过这种方式,您可以确保从相同的基础winsock提供程序获得侦听套接字,并且它支持AcceptEx()
  • 加载
    GetAcceptExSockaddrs()
    的方式与加载
    AcceptEx()
    的方式相同-一旦接受完成,您将需要它
  • 将侦听套接字与IOCP关联
  • 现在,您可以使用侦听套接字和您创建的新“accept”套接字发布大量的
    AcceptEx()
    调用,如下所示:

  • 创建一个设置有重叠的WSA\u标志的套接字
  • 将套接字与IOCP关联
  • 如上所述,您需要确保每个调用的缓冲区和重叠区都是唯一的,并且持续到完成为止

    完成时,您必须执行以下操作

  • 使用
    SO\u UPDATE\u ACCEPT\u CONTEXT调用已接受套接字上的
    setsockopt()
    ,使用侦听套接字作为数据
  • 使用
    GetAcceptExSockaddrs()
    解除锁定您的地址
  • 处理任何数据(如果在缓冲区中为数据分配了足够的空间)
  • 请注意,通过设计,
    AcceptEx()
    可用于接受新连接,并在一次操作中从该连接返回初始数据(在您知道自己在开始做事之前总是需要一些数据的情况下,这会带来稍好的性能,但如果您想防御仅通过连接而不发送数据就可以发起的拒绝服务攻击,则管理起来非常复杂——我写过这篇文章)

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


    请注意,Martin James对您的问题的最初评论实际上就是您要寻找的答案。不要通过Exputflen-((sizeof(sockaddr_in)+16)*2)<代码> > C++ >代码0 > <代码> .< /p>非零DWReVIEDATALATION,MSDN如果DWAVELVEDATATALLATE为零,接受连接不会导致接收操作。(sockaddr_in)+16)*2)在我的例子中是960,所以这不是问题..这不是问题:)做得好,+1用于超越问题并解释OP C风格代码的其他一些问题,(啊!)。我实际上认为,当接受完成发生时,重叠和数据缓冲区超出范围这一事实很可能是他没有获得任何完成的原因。我预计可能会发生访问冲突,完成被丢弃。OP:'但是,当客户端发送的数据完成了任务,感谢您的输入!但有一个问题,我应该在完成后还是在AcceptEx后调用WSARecv。目前我在完成后调用WSARecv,但由于尚未建立连接,因此得到了错误10057。我看对了吗?在AcceptEx完成并更新了ac后调用WSARecv通过调用setsockopt()接受接受套接字的上下文。