closesocket()未完成IOCP的挂起操作
closesocket() not completing pending operations of IOCP
我目前正在C++中开发一个服务器应用程序。我的主要灵感来自这些例子:
Windows SDK IOCP Excample
I/O完成端口IPv4/IPv6服务器程序示例
我的应用程序与这些非常相似(socketobj,packageobj,…)。
总的来说,我的应用程序运行时没有问题。唯一仍然给我带来麻烦的是半开放的关系。
我的策略是:我在一段时间内检查每个连接的客户端,并向上计数一个"空闲计数器"。如果出现一个完成,我会重置此计时器。如果Idle计数器过高,我会设置一个布尔值以防止其他线程发布操作,然后调用closesocket()
。
我的假设是,现在套接字已关闭,挂起的操作将完成(可能不是立即完成,而是在一段时间后完成)。这也是MSDN文档描述的行为(提示,第二段)。我需要这个,因为只有在所有操作完成后,我才能释放资源。
长话短说:我的情况并非如此。我用我的testclient应用程序进行了一些测试,并进行了一些cout和断点调试,发现关闭套接字的挂起操作没有完成(即使在等待10分钟后)。在closesocket()
之前,我也已经尝试过shutdown()
调用,两者都没有返回错误。
我做错了什么?这种情况发生在其他人身上吗?MSDN文档有错吗?有哪些替代方案?
我目前正在考虑"延迟"功能,或者使用CancelIoEx()
功能明确取消每个操作
编辑: (感谢您的回复)
昨天晚上,我为每个sockedobj添加了一个链表,以保存挂起操作的per-io-obj。有了这个,我尝试了CancelIOEx()
函数。对于大多数操作,函数返回0,GetLastError()
返回ERROR_NOT_FOUND。
在这种情况下,释放每个Io对象是否安全?
我还发现,当我在同一台机器上运行服务器应用程序和客户端应用程序时,这种情况更频繁。服务器无法完成写入操作的情况时有发生。我认为发生这种情况是因为客户端接收缓冲区已满。(客户端不会停止接收数据!)。
剪下的代码如下尽快。
- "linger"设置可以用于重置连接,但这样一来,您将(a)丢失数据,(b)向对等方发送重置,这可能会让对等方感到害怕
- 如果你正在考虑一个积极的延迟超时,这并没有真正的帮助
- 为读取而关闭应该会终止读取操作,但为写入而关闭只会在挂起的写入之后排队,因此根本没有帮助
- 如果挂起的写入是问题,并且没有完成,则必须取消它们
- 挂起和取消挂起一个文件DLL
- 如何防止C++遗留代码中的挂起指针
- 为什么所有C++编译器都会崩溃或挂起此代码
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 构建挂起,即使是适度的文件大小
- 循环挂起迭代的 std::擦除 on std::list
- Poco::Net::FTPClientSession 在 open() 方法上挂起 129 秒,如果 ftp 主机不存
- Node.js fs.open() 在尝试打开 4 个以上的命名管道 (FIFO) 后挂起
- 从不同进程中的另一个线程挂起/恢复线程或进程
- Boost (Beast) websocket:同步写入挂起
- 为什么析构函数挂起
- 使用互斥会挂起程序
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- closesocket()未完成IOCP的挂起操作
- QMutex是否需要是静态的,以便该类实例的其他线程调用知道要挂起它们的操作
- 显示MessageBox时,父窗口操作已挂起
- 如果 ssl::stream<tcp::socket 有挂起的操作,我是否不允许删除它>?
- 阻止取消Boost.Asio中挂起的异步操作
- 带有互锁操作的线程同步在Visual Studio 2013 c++原生代码中挂起
- WriteFile成功,即使缓冲区被挂起的操作覆盖