6

Twistedには、上に実装されたリアクターMsgWaitForMultipleObjectsが含まれます。どうやら、少なくともピアがいくつかのバイトを送信してからすぐに接続を閉じる場合、reactorにはTCP接続がいつ終了するかを確実に通知する問題があります。何が起こっているようです:

  1. リアクタはMsgWaitForMultipleObjects、いくつかのソケットハンドルとを使用して呼び出しますQS_ALLINPUT
  2. 呼び出しが完了し、この状態のソケットのハンドルがアクティブであることを示します(つまり、バイトが読み取られるのを待機していて、ピアによって閉じられています)。
  3. リアクタは、この通知を一般的な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.

これは、エッジトリガーのようには聞こえません。レベルトリガーのように聞こえます。

MsgWaitForMultipleObjects実際にエッジトリガーされていますか?それとも、レベルによってトリガーされ、この不正な動作は、その動作の他の側面によって引き起こされますか?

補遺 WSAEventSelectのMSDNドキュメントでFD_CLOSEは、基本的に1回限りのイベントであることを指摘するなど、ここで何が起こっているかについてもう少し説明しています。一度信号を送った後は、二度とそれを取得することはありません。これは、Twistedにこの問題がある理由を説明するのに役立ちます。MsgWaitForMultipleObjectsただし、この制限を考慮して、効果的に使用する方法については、まだ興味があります。

4

1 に答える 1

1

アクティビティを使用WSAEventSelectして区別するには、 を呼び出す必要がありますWSAEnumNetworkEvents。最初のイベントだけでなく、報告された各イベントを処理していることを確認してください。

WSAAsyncSelect原因の特定が容易になり、 と一緒に使用されることがよくありMsgWaitForMultipleObjectsます。

したがって、WSAAsyncSelectの代わりに使用できますWSAEventSelect

また、エッジトリガーとレベルトリガーの違いについて根本的な誤解があると思います。あなたの推論は、自動リセットと手動リセットのイベントに関連しているようです。

于 2011-09-29T16:14:59.307 に答える