对于与IOCP端口关联的套接字,WSARecv有时会返回"无效句柄(错误号6)".(C++)

nik*_*kgp 2 c++ windows network-programming tcp iocp

我正在尝试编写一个可以同时支持多个客户端连接的服务器,所以我正在尝试使用IOCP.让我简要介绍一下我的代码流程,然后我可以解释一下我的问题.首先,服务器正在打开一个端口,用于监听和等待对新传入连接的"接受"调用.作为参考,我使用了与此处提到的相同的代码.因此,它接受每个新的传入连接并返回一个新的套接字描述符(sd),然后它标记为非阻塞:

arg = 1;
ioctlsocket(sd, FIONBIO, &arg);
Run Code Online (Sandbox Code Playgroud)

然后启用TCP_NODELAY:

level = IPPROTO_TCP;
optName = TCP_NODELAY;
value = 1;
setsockopt(sd, level, optName, (const char*)&value, sizeof(value));
Run Code Online (Sandbox Code Playgroud)

此后与IOCP端口关联:

CreateIoCompletionPort((HANDLE)sd, iocp_port, (DWORD)completion_key, 4);
Run Code Online (Sandbox Code Playgroud)

completion_key是一个类对象,它只是一个容器,它包含数据缓冲区,重叠缓冲区,查询类型的recv/send等,并在最后发出一个读取调用:

WSARecv(sd, wsabuf, 1, &bytes, &flags, overlapped, NULL);
Run Code Online (Sandbox Code Playgroud)

wsabuf和overlapped是completion_key对象的一部分.

在90%的情况下,它工作正常,即当此套接字上有一些传入数据时,"GetQueuedCompletionStatus"被取消阻止,并且它具有有效数据.但有时WSARecv调用返回错误,GetLastError()返回6,这是"无效句柄"错误.我有点困惑为什么会发生这样的事情.

我正在创建一个iocp端口的方式:

iocp_port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
Run Code Online (Sandbox Code Playgroud)

并且有一些线程正在等待"GetQueuedCompletionStatus".

nik*_*kgp 6

我监控了后台发生的所有系统调用.WSARecv在内部调用NtDeviceIoControlFile,并且有一个参数"Event",它与作为hEvent的WSARecv的lpOverlapped结构中传递的参数相同.我没有将hEvent设置为NULL,因此它获取了一些垃圾值,当它为NULL时,NtDeviceIoControlFile成功返回,而在其他情况下,它返回"INVALID_HANDLE"错误.不幸的是,它大部分时间都是NULL.