- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
IOCP 服务器使用 WebSocket 连接。当浏览器发送关闭帧时,服务器删除
这个客户端,closesocket
函数调用客户端的对象析构函数。但即使在套接字关闭后,GetQueuedCompletionStatus
函数仍会继续从此套接字中选择事件。当然结果是false
,传输了0字节,但是Client ptr和OVERLAPPED
ptr不为NULL,GetLastError
返回1236(ERROR_CONNECTION_ABORTED)。 .. 所以是的,它被中止了,closesocket
被调用了......但为什么它还在这里???以及如何停止接收这种“无用”的事件?我可以在 thead 的循环中调用 continue
,但如果该函数将永远选择这个已删除的客户端,则会浪费 CPU 时间。
这是工作线程循环的一部分:
while(WAIT_OBJECT_0 != WaitForSingleObject(EventShutdown, 0)){
DWORD BytesTransfered = 0;
OVERLAPPED *asyncinfo = nullptr;
client *Client = nullptr;
BOOL QCS = GetQueuedCompletionStatus(hIOCP, &BytesTransfered, (PULONG_PTR)&Client, &asyncinfo, INFINITE);
if(!Client ) break;
switch( QCS * (BytesTransfered > 0) * Client->OpCode() ){
case OP_TYPE_RECV:{
.....
switch( recv_buf[0] &0xFF ){
....
case FIN_CLOSE:
printf("FIN_CLOSE on client %u\n", Client->Socket());
default:{
RemoveClient(Client);
break;
}
}
}
case OP_TYPE_SEND:{
...
}
default:{
printf("Client %u (%lu bytes transferred, QCS is %d)\n", Client->Socket(), BytesTransfered, QCS);
break;
}
客户端的析构函数:
client::~client(){
while(!HasOverlappedIoCompleted(&asyncinfo)) Sleep(0);
closesocket(socket);
if( a_ctx ) delete a_ctx;
if( q_ctx ) delete q_ctx;
delete [] data_buffer;
printf("Client %u deleted\n", socket);
}
...和服务器的日志:
Client 296 from 127.0.0.1 (agent 1987)
Client 308 from 127.0.0.1 (supervisor)
Client 324 from 127.0.0.1 (supervisor)
TOTAL: 3 client(s)
Sending 33278 bytes to 324
Send finished for 324
Send finished for 308
Sending 40529 bytes to 324
Send finished for 324
Sending 41128 bytes to 324
Send finished for 324
Sending 40430 bytes to 324
Send finished for 324
FIN_CLOSE on client 324
Client 324 deleted
Client 324 (0 bytes transferred, QCS is 0)
Client 324 (0 bytes transferred, QCS is 0)
Client 324 (0 bytes transferred, QCS is 0)
Client 324 (0 bytes transferred, QCS is 0)
Client 324 (0 bytes transferred, QCS is 0)
看到“324(传输了 0 个字节,QCS 为 0)”?套接字 324 已关闭。为什么它发生在析构函数的消息“Client 324 deleted”之后?
最佳答案
我认为您没有包含足够的代码来获得完整的图片,但这一行看起来很可疑:
switch( QCS * (BytesTransfered > 0) * Client->OpCode() ){
由于几个原因,这是有问题的。首先,GetQueuedCompletionStatus
不保证在成功时返回 1。 MSDN 只 promise 它将返回非零值。因此,依赖于成功案例的特定值(value)是有风险的。其次,您无法区分失败的调用和返回 0 字节的成功调用。您应该真正分离管理出队和调度特定 I/O 事件的逻辑。这将使您的代码更易于理解和维护。
您还必须记住,每个 socket 都有两个侧面。在用户空间中有与之关联的结构和套接字句柄,然后是管理低级细节的内核对象。仅仅因为您在用户端关闭了您的句柄并不意味着内核对象消失了。内核对象被引用计数并且通常会持续到涉及这些对象的所有 I/O 完成为止。
这就是为什么从程序的角度来看,在套接字被“销毁”后,您仍然可以获得套接字的 I/O 通知。特别是对于套接字,关闭序列将在您关闭句柄后发生(因为在此之前您没有明确关闭套接字)。
不是为了响应特定消息而销毁 Client 对象,只需关闭套接字句柄并清理其他结构以响应中止通知。您还可以考虑正常断开连接而不是中止连接。
关于c++ - GetQueuedCompletionStatus 继续在关闭的套接字上选择事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53393101/
我正在编写一个服务器应用程序,我想使用 IOCompletion 端口,所以我为服务器编写了一个原型(prototype),但我遇到了 GetQueuedCompletionStatus 的问题,它永
IOCP 服务器使用 WebSocket 连接。当浏览器发送关闭帧时,服务器删除这个客户端,closesocket函数调用客户端的对象析构函数。但即使在套接字关闭后,GetQueuedCompleti
我编写了基于 iocp 机制管理网络通信的复杂库。问题是,当服务器通过调用 API 方法 closesocket() 关闭连接时,此信息有时会延迟几秒甚至几分钟传输到客户端。我用于检测连接关闭的代码如
我有一个通过串行端口生成消息的设备。当我重新启动设备时,IO 完成端口停止读取字节。 代码是调用 GetQueuedCompletionStatus(): BOOL bRet = GetQueuedC
我有手工制作的线程池。线程从完成端口读取并做一些其他事情。必须结束一个特定的线程。如果它卡在 GetQueuedCompletionStatus() 或 GetQueuedCompletionStat
GetQueuedCompletionStatus() 将完成通知从队列中取出,但它不会返回通知的类型(例如读取通知、写入通知)。 我有责任跟踪我发起的操作,例如,当我使用 WSARecv() 时,我
让我先概括一下。我通过三个端口接收数据。我有一个套接字、一个完成端口和一个工作线程。我调用 WSARecv,工作线程进程调用 GetQueuedCompletionStatus,然后是我的解析例程 R
我一直在测试将 IO 完成端口与线程池中的工作线程相结合,并偶然发现了一个我无法解释的行为。特别是,虽然下面的代码: int data; for (int i = 0; i (&data));
在程序终止期间,如何取消阻塞先前已通过调用 GetQueuedCompletionStatus() 阻塞的线程? 最佳答案 您可以使用 PostQueuedCompletionStatus API 调
我正在尝试将 GetQueuedCompletionStatus 与 Winsocks 一起使用,但我似乎无法正确执行。流程如下: void foo() { ... SOCKET sc
我正在尝试使用 Winsock 创建一个依赖于 IO 完成端口的 UDP 客户端/服务器类,但我无法让 GetQueuedCompletionStatus() 函数在新数据可用时返回。这可能是由于我的
正如它听起来的那样,我正在尝试异步 ReadDirectoryChangesW 和 IO 完成,但它不起作用,具体来说,GetLastError 重复返回 258 (GetQueuedCompleti
当调用 WSASend() 时,我必须向它传递一个 WSAOVERLAPPED 实例,并且我不能重新使用这个 WSAOVERLAPPED 实例,直到先前的 WSASend() 操作已经完成(即当一个完
有两个原因可以导致GetQueuedCompletionStatus()失败(返回FALSE),第一个是因为在调用时关闭了与其关联的完成端口句柄是突出的,如果 lpOverlapped 是 NULL,
背景:我正在使用 CreateIoCompletionPort、WSASend/Recv 和 GetQueuedCompletionStatus 在我的服务器上执行重叠套接字 io。对于流量控制,当发
切换到 Windows 8 后,我的应用程序停止工作。我花了几个小时调试问题,发现 IOCP 的行为在 Windows 8 和以前的版本之间有所不同。我提取了必要的代码来演示和重现问题。 SOCKET
我是一名优秀的程序员,十分优秀!