1

私の問題:私のCompletionportサーバーは、さまざまなクライアントから不明なサイズのデータ​​を受信します。問題は、バッファオーバーランを回避する方法/(受信)バッファがデータで「いっぱいになる」のを回避する方法がわからないということです。

ここでQuesitonsに:1)WSARecvを介して受信呼び出しを行う場合、workerthreadはコールバック関数のように機能しますか?つまり、受信コールが完了したときにのみそれを掘り起こしますか、それとも受信が行われているときにもそれを掘り起こしますか?lpNumberOfBytes(GetQueuedCompletionStatusから)変数には、これまでに受信したバイト数または受信した合計バイト数が含まれていますか?

2)オーバーランを回避する方法、動的に割り当てられたバッファー構造を考えましたが、パッケージがどれだけ大きくなるかを知るにはどうすればよいですか?

編集:私はこれを尋ねるのは嫌いですが、バッファを管理し、オーバーランを回避するための「簡単な」方法はありますか?少なくとも今のところ、同期は私には立ち入り禁止に聞こえます

4

2 に答える 2

1

_1。完了ポートは一種のキューです(I / O完了をデキューするのを待機しているスレッドの優先順位に関する高度なロジックを備えています)。I / Oが(正常にまたは失敗して)完了すると、完了ポートにキューに入れられます。次に、と呼ばれるスレッドの1つによってデキューされGetQueuedCompletionStatusます。

「進行中」のI/Oをデキューしないようにします。さらに、ワーカースレッドによって非同期的に処理されます。つまり、スレッドがを呼び出すまで遅延しますGetQueuedCompletionStatus

_2。これは実際には複雑な問題です。同期は、特に対称マルチスレッド(複数のスレッドがあり、それぞれがすべてを実行している可能性があります)に関しては、全体として簡単な作業ではありません。

完了したI/Oで受け取るパラメーターの1つは、OVERLAPPED構造体へのポインターです(I / Oを発行した関数に指定したものなどWSARecv)。に基づく独自の構造を割り当てるのが一般的な方法ですOVERLAPPED(継承するか、最初のメンバーとして使用します)。完了を受け取ると、デキューさOVERLAPPEDれたデータを実際のデータ構造にキャストできます。ここには、同期に必要なすべてのものがあります。同期オブジェクト、状態の説明などです。

ただし、カスタムコンテキストがある場合でも、物事を正しく同期する(優れたパフォーマンスを実現し、デッドロックを回避する)ことは簡単な作業ではないことに注意してください。これには正確な設計が必要です。

于 2012-02-17T15:04:31.050 に答える
1

WSARecvを介して受信呼び出しを行う場合、workerthreadはコールバック関数のように機能しますか?

@valdoの投稿を参照してください。完了データはスレッドのプールにキューに入れられ、1つはそれを処理する準備が整います。

「つまり、受信コールが完了したときにのみ、受信コールを掘り起こしますか?」はい-それ故に名前。「完了」の意味は異なる場合があることに注意してください。プロトコルによって異なります。TCPの場合、ストリーミングされたデータバイトがピアから受信されたことを意味します。

'lpNumberOfBytes(GetQueuedCompletionStatusから)変数には、これまでに受信したバイト数または受信した合計バイト数が含まれていますか?' これには、そのIOCP完了でのみ提供される、受信されてバッファー配列にロードされたバイト数が含まれます。

「オーバーランを回避する方法、動的に割り当てられたバッファ構造を考えましたが、パッケージがどれだけ大きくなるかを知るにはどうすればよいですか?」バッファ配列を指定した場合、オーバーランを取得することはできません。バッファをロードするカーネルスレッドは、渡されたバッファ長を超えません。アプリケーションレベルでは、TCPのストリーミングの性質を考えると、バッファ配列を使用可能なアプリケーションレベルのプロトコルユニットに処理する方法を決定するのはあなた次第です。提供されるサービスに関する知識を使用して、適切なバッファ管理スキームを決定する必要があります。

最後のIOCPサーバーはやや汎用的でした。起動時に割り当てられたバッファプールの配列と「buffer-carrier」オブジェクトのプールを(ソケットオブジェクトのプールとともに)使用しました。各バッファープールは、異なるサイズのバッファーを保持していました。新しい接続時に、最小のプールから1つのバッファーを使用してWSARecvを発行しました。このバッファーが完全にいっぱいになった場合は、次に大きいプールのバッファーを次のWSARecvに使用しました。

次に、複数のハンドラスレッドでの順不同のバッファリングを防ぐために必要なシーケンス番号の問題があります:(

于 2012-02-17T15:28:27.857 に答える