ブロッキングソケットにデータを非常に高速に書き込むと仮定します[すべてのデータがメモリにあります]。さらに、反対側がデータを非常に遅く読み取ると仮定します[各読み取りの間に1秒のスリープなど]。
この場合、書き込み側で予想される動作は何ですか?反対側が十分なデータを読み取るまで書き込み操作はブロックされますか、それとも書き込みは接続リセットなどのエラーを返しますか?
ブロッキングソケットの場合、send()
呼び出しは、すべてのデータがその接続用のネットワークスタックのバッファにコピーされるまでブロックされます。反対側が受け取る必要はありません。このバッファのサイズは実装によって異なります。
リモート側がデータを確認すると、データはバッファからクリアされます。これはOSのものであり、リモートに依存しませんアプリケーション実際にデータを読み取ります。このバッファのサイズも実装に依存します。
リモートバッファがいっぱいになると、ローカルスタックに送信を停止するように指示します。データがリモートバッファからクリアされると(リモートアプリケーションによって読み取られることにより)、リモートシステムはローカルシステムにさらにデータを送信するように通知します。
どちらの場合も、小規模なシステム(組み込みシステムなど)には数KB以下のバッファーがあり、最新のサーバーには数MB以上のバッファーがある場合があります。
ローカルバッファに空きができると、send()
呼び出しからのデータがさらにコピーされます。そのデータがすべてコピーされると、通話が返されます。
接続が実際にリセットされない限り、「接続リセット」エラーは発生しません(OSから-ライブラリは何でも実行できます)。
つまり...ローカルとリモートの両方のバッファサイズを合わせた量のデータを送信するまで、リモートアプリケーションがデータを読み取る速度は実際には重要ではありません。その後は、リモート側がsend()
するのと同じ速さでrecv()
を実行できるようになります。
出力(送信)バッファはいっぱいになるまでいっぱいになり、バッファがパケットをキューに入れるのに十分なほど解放されるまでsend()
ブロックします。
マニュアルページを送信すると言うように:
メッセージがソケットの送信バッファーに収まらない場合、ソケットが非ブロッキングI/Oモードになっていない限り、send()は通常ブロックします。
これを見てください: http://manpages.ubuntu.com/manpages/lucid/man2/send.2.html