1

私はクライアント/サーバーのペアを実装し、TCP/IP ソケットを介して通信し、Windows の完了ルーチンでオーバーラップ IO を使用しています。デバッグは、2 つの VirtualBox 仮想マシン (1 つはクライアント、もう 1 つはサーバー) で行われています。CPUはクアッドコア。

クライアントでの一連の操作は、基本的に次のとおりです。

  • WSARecv 呼び出しを発行します (まだ完了しません)。
  • パケットで WSASend 呼び出しを発行します。サーバーは同じソケットを介して応答を送信します。
  • WSASend 呼び出しの完了ルーチンが実行されると、パケットは応答待ちキューに入れられます。
  • WSARecv 呼び出しの完了ルーチンが実行されると (サーバーからの応答が受信されると)、コードはこの応答に関連するパケットをキュー内で見つけようとします。
  • WSARecv 呼び出しを発行します (まだ完了しません)。
  • 2 番目のステップから繰り返します。

サーバーでの一連の操作は基本的に次のとおりです。

  • WSARecv 呼び出しを発行します (まだ完了しません)。
  • WSARecv 呼び出しの完了ルーチンが実行されると (クライアントからのパケットが受信されると)、パケットはセカンダリ スレッドで処理されます。
  • WSARecv 呼び出しを発行します (まだ完了しません)。
  • セカンダリ スレッドが完了すると、応答がクライアントに送信され、プライマリ スレッドで WSASend 呼び出しが発行されます。
  • 2 番目のステップから繰り返します。

私が抱えている問題は、応答待ちキューに対応するパケットがなくても、クライアントで応答が受信されることがあることです。デバッグ作業の一環として、2 つの質問があります。

1) 保留中の WSARecv 呼び出しがある場合、対応する WSASend (サーバーが応答したパケットを送信したもの) の完了ルーチンよりも前に、WSARecv の完了ルーチンの実行がスケジュールされていると考えられますか?

2) WSASend 呼び出しがすぐに完了する場合、完了ルーチンがまだ実行のためにスケジュールされていますか?

警告可能な待機関数として WSAWaitForMultipleEvents 呼び出しを使用しています。

4

1 に答える 1

1

あなたのコードは壊れています。操作が特定の順序で完了することが保証されていたとしても、完了指示が特定の順序で受信されたことや、それらの完了を処理するコードが特定の順序で実行されることは保証されません。

2 番目の質問に対する答えはyesです。通常、完了ルーチンはどちらの場合でも実行されるため、即時完了を保留中と同じように扱うことができます。

問題の理想的な解決策は、パケットを送信するとすぐに応答を待っていると見なすことです。

何らかの理由でコードの変更が多すぎる場合は、別の選択肢があります。WSARecv 完了を受け取り、WSASend 完了がまだ発生していない場合は、単に WSARecv 完了の処理を延期します。これを行うには、次の 2 つの方法があります。

  1. スレッドを生成して一瞬だけ待機し、そのスレッドから ( を呼び出して) 完了通知を再送信PostQueuedCompletionStatusします。おそらく、WSASend はそれまでに完了しているでしょう。

  2. WSARecv が完了したフラグをマークし、完了情報を保存します。WSASend が完了したら、そのフラグに注意して、WSARecv を処理します。(おそらく、完了ハンドラを直接呼び出すことによって。)

于 2012-06-06T09:21:52.440 に答える