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

时间:2011-09-29 14:35:01

标签: python windows networking twisted reactor

Twisted包含a reactor implemented on top of MsgWaitForMultipleObjects。显然,反应堆在TCP连接何时结束时可靠地注意到,至少在对等体发送一些字节然后快速关闭连接的情况下。似乎发生的事情是:

  1. The reactor calls MsgWaitForMultipleObjects with some socket handles and QS_ALLINPUT.
  2. 调用完成并指示处于此状态的套接字的句柄(即,等待读取并且已被对等方关闭的字节)处于活动状态。
  3. The reactor dispatches this notification to the common TCP implementation.
  4. TCP实现从套接字读取可用字节。有一些,他们被交付给应用程序代码。
  5. 控制权返回到反应堆,最终再次调用MsgWaitForMultipleObjects
  6. MsgWaitForMultipleObjects永远不再表示句柄处于活动状态。 TCP实现永远不会再次查看套接字,因此它永远无法检测到连接已关闭。
  7. 这使得MsgWaitForMultipleObjects似乎是边缘触发的通知机制。 MSDN documentation说:

    Waits until one or all of the specified objects are in the signaled state
    or the time-out interval elapses.
    

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

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

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

1 个答案:

答案 0 :(得分:1)

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

WSAAsyncSelect可以轻松确定原因,并且通常与MsgWaitForMultipleObjects一起使用。

因此,您可以使用WSAAsyncSelect代替WSAEventSelect

另外,我认为你对边缘触发和水平触发之间的区别有一个根本的误解。你的推理似乎与自动重置和手动重置事件有关。