web-dev-qa-db-ja.com

反対側が読み取るよりも速く、ブロッキングソケットにデータを書き込むとどうなりますか?

ブロッキングソケットにデータを非常に高速に書き込むと仮定します[すべてのデータがメモリにあります]。さらに、反対側がデータを非常に遅く読み取ると仮定します[各読み取りの間に1秒のスリープなど]。

この場合、書き込み側で予想される動作は何ですか?反対側が十分なデータを読み取るまで書き込み操作はブロックされますか、それとも書き込みは接続リセットなどのエラーを返しますか?

21
Aviad Rozenhek

ブロッキングソケットの場合、send()呼び出しは、すべてのデータがその接続用のネットワークスタックのバッファにコピーされるまでブロックされます。反対側が受け取る必要はありません。このバッファのサイズは実装によって異なります。

リモート側がデータを確認すると、データはバッファからクリアされます。これはOSのものであり、リモートに依存しませんアプリケーション実際にデータを読み取ります。このバッファのサイズも実装に依存します。

リモートバッファがいっぱいになると、ローカルスタックに送信を停止するように指示します。データがリモートバッファからクリアされると(リモートアプリケーションによって読み取られることにより)、リモートシステムはローカルシステムにさらにデータを送信するように通知します。

どちらの場合も、小規模なシステム(組み込みシステムなど)には数KB以下のバッファーがあり、最新のサーバーには数MB以上のバッファーがある場合があります。

ローカルバッファに空きができると、send()呼び出しからのデータがさらにコピーされます。そのデータがすべてコピーされると、通話が返されます。

接続が実際にリセットされない限り、「接続リセット」エラーは発生しません(OSから-ライブラリは何でも実行できます)。

つまり...ローカルとリモートの両方のバッファサイズを合わせた量のデータを送信するまで、リモートアプリケーションがデータを読み取る速度は実際には重要ではありません。その後は、リモート側がsend()するのと同じ速さでrecv()を実行できるようになります。

33
Brian White

出力(送信)バッファはいっぱいになるまでいっぱいになり、バッファがパケットをキューに入れるのに十分なほど解放されるまでsend()ブロックします。

マニュアルページを送信すると言うように:

メッセージがソケットの送信バッファーに収まらない場合、ソケットが非ブロッキングI/Oモードになっていない限り、send()は通常ブロックします。

これを見てください: http://manpages.ubuntu.com/manpages/lucid/man2/send.2.html

6
Davide Berra