我目前正在使用C++编写服务器应用程序。我的主要启示有这些例子:closesocket()未完成IOCP的挂起操作
The I/O Completion Port IPv4/IPv6 Server Program Example
我的应用程序是强烈类似于这些(socketobj,packageobj,...)。
一般来说,我的应用程序运行没有问题。仍然导致我麻烦的唯一的事情是半开放的连接。
我的策略是:我在一段时间内检查每个连接的客户端,并计算一个“空闲计数器”。如果发生一次完成,我重置这个计时器。如果空闲计数器变得太高,我设置一个布尔值来防止其他线程发布操作,然后致电closesocket()
。
我的假设是,现在套接字已关闭,挂起的操作将完成(可能不会立即但一段时间后)。这也是MSDN文档描述的行为(提示,第二段)。我需要这个,因为只有在所有操作完成后才可以释放资源。
长话短说:这不适合我。我用我的testclient应用程序和一些cout和断点调试做了一些测试,发现关闭套接字的挂起操作没有完成(即使在等待10分钟后)。我也已经尝试在closesocket()
之前拨打shutdown()
,并且都没有返回任何错误。
我在做什么错?其他人也有遇到同样的状况吗? MSDN文档是否错误?有什么选择?
我目前想的“苟延残喘”的功能,或与CancelIoEx()
功能明确取消每个操作
编辑:(谢谢你的回复)
昨天晚上我为每个sockedobj添加了一个链接列表来保存待处理操作的每个io obj。有了这个,我尝试了CancelIOEx()
函数。对于大多数操作,函数返回0和GetLastError()
返回ERROR_NOT_FOUND。
在这种情况下释放每个Io Obj是否安全?
我还发现,当我在同一台机器上运行我的服务器应用程序和客户端应用程序时,发生这种情况的频率更高。它偶尔会发生,服务器不能完成写入操作。我认为这是因为客户端接收缓冲区已满而发生的。 (客户端不会停止接收数据!)。
尽快切断代码。
请提供[mcve]。 –
如果接收方没有收到,*当然*发送方将阻塞,除非他处于非阻塞模式,哪个IOCP不是。您测试无效。 – EJP
@EJP这是否意味着,我不可能事先检测到这一点?看起来'WSASend()'可以发布,但它永远不会完成。我该如何改进测试? – Woife