0

我目前正在使用 C++ 开发服务器应用程序。我的主要灵感是这些例子:

Windows SDK IOCP 示例

I/O 完成端口 IPv4/IPv6 服务器程序示例

我的应用程序与这些(socketobj、packageobj、...)非常相似。

一般来说,我的应用程序运行没有问题。唯一仍然给我带来麻烦的是半开连接。

我的策略是:我在一段时间内检查每个连接的客户端并计算一个“空闲计数器”。如果发生一次完成,我会重置此计时器。如果空闲计数器太高,我设置一个布尔值以防止其他线程发布操作,然后调用closesocket().

我的假设是,现在套接字已关闭,待处理的操作将完成(可能不是立即完成,而是在一段时间后)。这也是 MSDN 文档描述的行为(提示,第二段)。我需要这个,因为只有在完成所有操作之后才能释放资源。

长话短说:这对我来说不是这样。我用我的 testclient 应用程序和一些 cout 和断点调试做了一些测试,发现关闭套接字的挂起操作没有完成(即使在等待 10 分钟之后)。我也已经在 之前尝试过shutdown()调用closesocket(),并且都没有返回错误。

我究竟做错了什么?其他人也有遇到同样的状况吗?MSDN 文档有错吗?有哪些替代方案?

我目前正在考虑“逗留”功能,或者使用该CancelIoEx()功能明确取消每个操作

编辑:( 感谢您的回复)

昨天晚上我为每个 sockedobj 添加了一个链表来保存挂起操作的 per io obj。有了这个我尝试了这个CancelIOEx()功能。对于大多数操作,该函数返回 0 并GetLastError()返回ERROR_NOT_FOUND 。

那么在这种情况下释放每个 Io Obj 是否安全?

我还发现,当我在同一台机器上运行我的服务器应用程序和客户端应用程序时,这种情况发生得更频繁。有时会发生服务器无法完成写入操作的情况。我认为这是因为客户端接收缓冲区已满。(客户端不会停止接收数据!)。

剪断的代码会尽快跟进。

4

1 回答 1

1
  • 'linger' 设置可用于重置连接,但这样您将 (a) 丢失数据并 (b) 向对等方发送重置,这可能会吓到它。
  • 如果您正在考虑积极的逗留超时,它并没有真正帮助。
  • 关闭读取应该终止读取操作,但关闭写入仅在挂起的写入之后排队,因此它根本没有帮助。
  • 如果挂起的写入是问题,并且未完成,则必须取消它们。
于 2017-10-12T07:00:09.217 回答