如何使用MsgWaitForMultipleObjects可靠地检测断开连接的TCP套接字?

Jea*_*one 6 python windows networking twisted reactor

扭曲包括在顶部实施的反应堆MsgWaitForMultipleObjects.显然,反应堆在TCP连接何时结束时可靠地注意到,至少在对等体发送一些字节然后快速关闭连接的情况下.似乎发生的事情是:

  1. 反应器调用MsgWaitForMultipleObjects一些套接字句柄和QS_ALLINPUT.
  2. 调用完成并指示处于此状态的套接字的句柄(即,具有等待读取且已被对等方关闭的字节)处于活动状态.
  3. reactor将此通知分派给公共TCP实现.
  4. TCP实现从套接字读取可用字节.有一些,它们被交付给应用程序代码.
  5. 控制返回到反应堆,最终MsgWaitForMultipleObjects再次调用.
  6. MsgWaitForMultipleObjects永远不再表示句柄处于活动状态.TCP实现永远不会再次查看套接字,因此它永远不会检测到连接已关闭.

这使它看起来好像MsgWaitForMultipleObjects是边缘触发的通知机制.在MSDN文档说:

Waits until one or all of the specified objects are in the signaled state
or the time-out interval elapses.
Run Code Online (Sandbox Code Playgroud)

这听起来不像是边缘触发.这听起来像是水平触发.

MsgWaitForMultipleObjects实际边沿触发?或者它是否被水平触发,这种不当行为是由其行为的其他方面引起的?

附录 WSAEventSelect的MSDN文档解释了这里发生了什么,包括指出这FD_CLOSE基本上是一次性事件.在发出一次信号之后,你再也不会得到它了.这在某种程度上解释了为什么Twisted有这个问题.不过,我仍然有兴趣听听如何有效地使用MsgWaitForMultipleObjects这个限制.

Ben*_*igt 1

为了使用WSAEventSelect和区分活动,您需要调用WSAEnumNetworkEvents. 确保您正在处理报告的每个事件,而不仅仅是第一个事件。

WSAAsyncSelect便于确定原因,常与 一起使用MsgWaitForMultipleObjects

所以你可以使用WSAAsyncSelect而不是WSAEventSelect.

另外,我认为您对边沿触发和电平触发之间的差异有根本性的误解。您的推理似乎与自动重置与手动重置事件更相关。