C++ IOCP AcceptEx在连接时未创建完成
我目前正在尝试一些用于套接字编程的新库(IOCP)。我偶然发现了启用异步连接的功能 正如文件所说: 与accept函数不同,AcceptEx函数使用重叠的I/O。如果您的应用程序使用AcceptEx,它可以使用相对较少的线程为大量客户机提供服务。与所有重叠的Windows功能一样,Windows事件或完成端口都可以用作完成通知机制 但当客户连接时,我没有收到任何完成。然而,当客户端发送数据时,我确实得到了一个完成 这是我的代码:C++ IOCP AcceptEx在连接时未创建完成,c++,windows,winsock,iocp,C++,Windows,Winsock,Iocp,我目前正在尝试一些用于套接字编程的新库(IOCP)。我偶然发现了启用异步连接的功能 正如文件所说: 与accept函数不同,AcceptEx函数使用重叠的I/O。如果您的应用程序使用AcceptEx,它可以使用相对较少的线程为大量客户机提供服务。与所有重叠的Windows功能一样,Windows事件或完成端口都可以用作完成通知机制 但当客户连接时,我没有收到任何完成。然而,当客户端发送数据时,我确实得到了一个完成 这是我的代码: DWORD dwBytes; GUID GuidAcceptEx
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()
之前,需要执行这些操作
AcceptEx()
,并调用WSAIoctl
(严格来说不是必需的,您显示的代码应该可以工作,但通过这种方式,您可以确保从相同的基础winsock提供程序获得侦听套接字,并且它支持AcceptEx()GetAcceptExSockaddrs()
的方式与加载AcceptEx()
的方式相同-一旦接受完成,您将需要它AcceptEx()
调用,如下所示:
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()接受接受套接字的上下文。