Rob*_*rtH 2 c++ windows winsock iocp
我目前正在尝试一些用于套接字编程的新库(IOCP).我偶然发现了AcceptEx功能来启用异步连接.
正如文件所说:
与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();
}
Run Code Online (Sandbox Code Playgroud)
然后:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
有关接受完成的建议吗?
编辑:我在m_lpfnAcceptEx()之后将hSocket绑定到完成端口
Len*_*ate 10
首先,当你完成调用时,你在调用WSAOVERLAPPED之上的堆栈上声明的数据缓冲区AcceptEx()将不存在(除非你调用GetQueuedCompletionStatus()相同的函数,这将是一个奇怪的事情).您需要动态分配它们或将它们集中在一起.
其次,您声明在调用后将套接字与完成端口关联AcceptEx().那是错的.你打电话之前需要做这些事情AcceptEx().
WSA_FLAG_OVERLAPPEDset 创建一个套接字.AcceptEx()使用侦听套接字动态加载并调用WSAIoctl(不是绝对必要的,并且您显示的代码应该可以工作,但这样您可以确保从相同的底层winsock提供程序获取侦听套接字并且它支持AcceptEx().GetAcceptExSockaddrs()以与加载相同的方式加载AcceptEx()- 一旦接受完成,您将需要它.现在,您可以AcceptEx()使用侦听套接字和您创建的新"accept"套接字发布一些调用,如下所示:
WSA_FLAG_OVERLAPPEDset 创建一个套接字.如上所述,您需要确保缓冲区和OVERLAPPED在每次调用时都是唯一的,并且一直持续到完成.
完成后,您必须执行以下操作....
setsockopt()与SO_UPDATE_ACCEPT_CONTEXT使用监听套接字作为数据接受套接字上...GetAcceptExSockaddrs().请注意,通过设计AcceptEx()可以用于接受新连接并在一次操作中从该连接返回初始数据(这会导致在您开始做事之前总是想要一些数据然后可怕的情况下稍微提高性能复杂的管理,如果你想要防止拒绝服务攻击,只需通过连接和不发送数据启动 - 我在这里写了这个).
如果您不想AcceptEx()等待数据到达,那么只需提供一个足够大的数据缓冲区,以便返回地址并将0作为"缓冲区大小"传递.一旦建立连接,这将导致AcceptEx()像重叠一样操作accept()并返回.
请注意,Martin James对您问题的初步评论实际上就是您正在寻找的答案.不要通过outBufLen - ((sizeof (sockaddr_in) + 16) * 2),通过0.