Vladの答えは興味深いですが、OSにとらわれず理論的です。ここでは、IOCP の設計上の考慮事項にもう少し焦点を当てています。
TCP 接続からメッセージのストリームを読み取っているようです。これにより、メッセージは完全なメッセージの長さを詳述するヘッダーで構成されます。ヘッダーは固定サイズで、9 バイトです。
オーバーラップした各読み取り完了は、1 バイトとバッファーのサイズの間で返されることに注意してください。9 バイトの読み取りを発行して、常に完全なヘッダーを取得できると想定してはいけません。完全なメッセージに十分な大きさのバッファーを使用して、読み取りが完了したときにそのメッセージ全体を受信します。予想よりも少ないバイトを返す完了に対処する必要があります。これに対処する最善の方法は、WSABUF ポインターをバッファーの先頭に調整して、後続のオーバーラップ読み取りがその位置のバッファーにより多くのデータを読み取るようにすることです。この読み物が終わった直後に...
データを読み取る最良の方法は、次のことによって異なります。
- どれくらい大きいか (平均および可能な最大のメッセージサイズ)
- 処理する可能性のある接続の数
- メッセージを分割して処理できるか、完全なメッセージとしてのみ処理できるか。
- ピアがあなたからの応答なしに複数のメッセージを送信できるかどうか、またはそれが「メッセージ応答」スタイルのプロトコルであるかどうか。
IOCP を使用してデータを読み取る方法に関する決定のほとんどは、データのコピーが行われる場所と、処理しているデータをどの程度便利にしたいかによって決まります。ソケット レベルの読み取りバッファリングをオフにしていないと仮定すると、データを読み取るたびにデータ コピーが発生する可能性があります。TCP スタックはソケットごとの読み取りバッファーにデータを蓄積し、重複した読み取りはこれを独自のバッファーにコピーして返します。
最も簡単な状況は、メッセージが到着したときにメッセージを分割して処理できる場合です。この場合、単純にフル バッファ サイズのオーバーラップ読み取りを発行し、完了を処理し (バッファには 1 バイトからバッファ サイズのデータが含まれます)、新しい読み取りを (おそらく同じバッファの最後に) 発行します。処理するのに十分なデータを取得し、さらに読み取る必要があるまでデータを処理します。これの利点は、(バッファー サイズに対して) 最小数のオーバーラップ読み取りを発行することであり、これにより、ユーザー モードからカーネル モードへの遷移が減少します。
メッセージを完全なメッセージとして処理しなければならない場合、それらの処理方法は、メッセージの大きさとバッファの大きさによって異なります。(バッファーの長さが 9 バイトのみであることを指定することによって) ヘッダーの読み取りを発行し、さらに重複した読み取りを発行して、完全なメッセージを 1 つ以上のバッファーに蓄積することができます (バッファーの開始と長さを調整することによって)。 「接続ごと」のデータ構造内でバッファを連鎖させます。または、ヘッダーに対して「特別な」読み取りを発行せず、1 回の読み取りで複数のメッセージが返される可能性に対処します。
私は、このようなことのほとんどを行う IOCP サーバーの例をいくつか持っています。ここからダウンロードして、付随する記事でそれらについて読むことができます。