3

私は英語のネイティブ スピーカーではないので、何かが足りないかもしれません。

MSDN でのWSASendの資料から引用:

lpBuffers [入力]

WSABUF 構造体の配列へのポインター。各 WSABUF 構造体には、バッファーへのポインターと、バッファーの長さ (バイト単位) が含まれています。Winsock アプリケーションの場合、WSASend 関数が呼び出されると、システムがこれらのバッファを所有し、アプリケーションはそれらにアクセスできなくなります。この配列は、送信操作の間有効である必要があります。

わかりました、太字のテキストが見えますか? そこがわかりにくいところ!

この行には 2 つの翻訳が考えられます (別の名前を付けてもかまいません):
翻訳 1 - 「バッファ」は、この関数を呼び出すときに渡す OVERLAPPED 構造体を指します。オブジェクトに関する完了通知を受け取った場合にのみ、オブジェクトを再利用できます。
翻訳 2 - 「バッファ」とは、送信しているデータを含む実際のバッファを指します。WSABUF オブジェクトが 1 つのバッファーを指している場合、操作が完了するまでこのバッファーにアクセスできません。

その行の正しい解釈を誰か教えてもらえますか?

そして..... 答えが 2 番目の場合、どのように解決しますか?
私にとっては、送信しているすべてのデータ/バッファについて、送信者側でそのコピーを保持する必要があることを意味するため、トラフィックの多いアプリケーションに多くの「保留中」のバッファ (さまざまなサイズ) があり、実際に「スケーラビリティ」を損なう。

ステートメント 1:
上記の段落 (「And....」) に加えて、SO_SNDBUFをゼロに設定しない限り、IOCP は送信するデータを独自のバッファーにコピーし、そこから送信すると考えました。

ステートメント 2:
スタックに割り当てられたバッファーを使用します (ご存知のとおり、char cBuff[1024];関数本体のようなものです。主な質問への変換が 2 番目のオプションである場合 (つまり、バッファーは送信が完了するまでそのままにしておく必要があります)、その後...それは本当に物事を台無しにします! それを解決する方法を考えられますか? (私は知っています、言い換えれば上記で尋ねました)。

4

1 に答える 1

4

答えは、オーバーラップした構造とデータバッファ自体は、操作が完了するまで再利用または解放できないということです。

これは、操作が非同期で完了するためです。データが最終的にTCP / IPスタックのオペレーティングシステム所有のバッファーにコピーされた場合でも、将来のある時点まで発生しない可能性があり、書き込み完了が発生すると通知されます。明示的なフロー制御なしで送信し、TCPスタックに依存してフロー制御を行う場合、書き込み完了でこれらが驚くほどの時間遅延する可能性があることに注意してください(ここを参照:WSASendを使用した一部のオーバーラップがタイムリーに返されないGetQueuedCompletionStatusを使用する方法?)..。

オーバーラップした構造にイベントを配置し、非同期操作が完了するまでブロックしない限り、スタックに割り当てられたバッファーを使用することはできません。通常のブロッキング呼び出しに複雑さを追加し、非同期呼び出しを発行してそれを待つことによって大きな利益を得ることはないので、それを行うことには多くの意味がありません。

私のIOCPサーバーフレームワーク(ここから無料で入手できます)では、OVERLAPPED構造を含み、参照カウントされる動的に割り当てられたバッファーを使用します。これは、完了が発生して参照が解放されたときに、クリーンアップ(私の場合は再利用のためにプールに戻される)が行われることを意味します。また、操作後もバッファの使用を継続することを選択でき、クリーンアップは引き続き簡単です。

こちらもご覧ください:I / O完了ポート、ソケットごとのコンテキストとI/Oごとのコンテキストを解放する方法

于 2010-06-13T10:47:58.657 に答える