selectが戻り、tcp ソケットに書き込み fd が設定された後。そのソケットでデータを送信しようとすると、send apiを使用して一度に送信されるデータの最小保証サイズはどれくらいですか? すべてのデータが確実に送信されるようにループを実行する必要があることを理解しています。それでも、送信される最小保証データとその理由を理解したいですか?
4 に答える
これは前にも出てきました。私はまだ参照された答えを探しています。
send() の関数プロトタイプから始めましょう
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
TCP ソケットをブロックする場合- エラーがない限り、send() と write() は [1..len] の間の値を返すことがすべてのドキュメントで示唆されています。しかし、現実には、1 回の呼び出しですべての「buf」が送信されたことを示すために、send() が -1 (エラー) または成功の場合に「len」以外の値を返すことを確認した人は誰もいません。私はこれに満足したことがないので、防御的にコーディングし、バッファー全体が送信されるまで、ブロッキング送信呼び出しをループに入れます。
非ブロッキング TCP ソケットの場合、最小値が "1" (またはエラーの場合は -1) であるかのようにコーディングする必要があります。最小データ サイズについて仮定しないでください。
また、recv() については、recv() が成功の場合は 1..len、0 (クローズ)、または -1 (エラー) の間のランダムな値を返すと常に想定する必要があります。recv が完全なバッファを返すとは決して想定しないでください。
POSIXレイヤーでは、それを制御できるとは思いません。send() は、TCP/IP スタック実装の内部バッファーに渡すものをすべて受け入れます。次に何が起こるかは、同じ select() 呼び出しを使用して監視できる別の話です。
MTU である 1 つのパケットに収まるサイズについて質問している場合 (ただし、この仮定は途中でのパケットの断片化と再構成に関しても注意して使用する必要があります)
更新:
ここであなたのコメントにお答えします。いいえ、断片化についてまったく気にする必要はありません。TCP/IP スタックにお任せください。これを行うべきではない理由はたくさんあります。例として 1 つ。あなたのアプリケーションは、OSI モデルの Application(7) 層で動作します (ほとんどの場合、OSI モデルは悪いことだと私は考えていますが、この例には実際に当てはまります)。そして、このレイヤーから、はるかに下のレイヤー (セッション/トランスポート) にあるロジックの機能/プロパティに影響を与えようとしています。これを行うべきではありません。send()、recv() などの POSIX 呼び出しは、特定の量のデータを渡す必要があることをレイヤーの下に指示する機能をアプリケーションに与えるように設計されており、コマンド (select()) の実行を監視する方法があります。あなたがしなければならないすべて。
UPD2: 上記のすべては、主に NON_BLOCKING ソケットを考慮しています。これについて言及するのを忘れて申し訳ありません。私は自分のプロジェクトでブロッキング ソケットを何年も使用していません。これを最適化すると、OS/ドライバーに非常に依存するコードになる可能性があります。
O_NONBLOCK
記述子は、関数がデータを正常に転送するかどうかに関係なく、出力関数への clear の呼び出しがブロックされない場合、書き込みの準備ができていると見なされます。
ご覧のとおり、実際にはサイズについて言及されておらず、書き込みが成功することさえありません。ブロックせずにソケットに書き込むことができるというだけです。
したがって、最小保証サイズはありません。