10

非blockigUDPソケットからrecv()/ recvfrom()が何を返すかを理解するのに問題があります。

TCPと比較してもう少し具体的です(私が間違っている場合は訂正してください):

  • ブロッキングソケット(TCPまたはUDP)は、バッファにデータが存在するまで、recv()から戻りません。これは、バイト数(TCP)または完全なデータグラム(UDP)である可能性があります。

  • 非ブロッキングTCPソケットは、EWOULDBLOCK(linux)/ WSAEWOULDBLOCK(windows)または現在バッファーにあるバイトのいずれかを返します。TCPデータはストリームであるため、返されるバイト数は関係ありません。

今の質問:

  • 利用可能なデータがない場合、非ブロッキングUDPソケットはWOULDBLOCK(linux)/ WSAEWOULDBLOCK(windows)も返します。しかし、利用可能なデータがある場合、非ブロッキングUDPソケットはほんの数バイトを返しますか?つまり、データグラムの半分しか取得できないのでしょうか、それともUDPソケットは常に完全なデータグラムを返すのでしょうか?

編集:

「データグラムの半分」とは、ソケットが現在データグラムを受信して​​いる瞬間にrecv()を呼び出すとどうなるかということです。その瞬間、バッファにいくつかのバイトがありますが、データグラムはまだ完成していません。

説明やコメントをいただければ幸いです。ありがとう!

4

3 に答える 3

10

最後に、私の古いオフィスの箱から私のスティーブンスの本を掘り出す言い訳。

バッファが十分に大きい場合、標準のバークレーソケットrecv()およびrecvfrom()関数が部分的なデータグラムを返すことはありません。カーネルがデータグラムを完全に受信して再アセンブルするまで、データグラムはアプリケーションで使用できません。

興味深いことに、これは今日の問題ではありませんが、他のネットワークプログラミングインターフェイスは、提供されたバッファが小さすぎる場合の動作に同意しません。

従来のバークレーバージョンのソケットAPIはデータグラムを切り捨て、余分なデータを破棄します。アプリケーションに通知されるかどうかは、バージョンによって異なります。(4.3BSD Reno以降は、データグラムが切り捨てられたことをアプリケーションに通知できます。)

SVR4(Solaris 2.xを含む)のソケットAPIは、データグラムを切り捨てません。余分なデータは、後続の読み取りで返されます。アプリケーションは、単一のUDPデータグラムから複数の読み取りが実行されていることを通知されません。

TLIAPIはデータを破棄しません。代わりに、より多くのデータが利用可能であることを示すフラグが返され、アプリケーションによる後続の読み取りは残りのデータグラムを返します。

(Stevens、TCP / IP Illustrated、Volume 1、p.160)

于 2010-02-10T22:16:39.557 に答える
2

はい、UDPはその1つのデータグラムで送信されたデータを返すだけです。UDPはTCPのようにストリーム指向ではありません。データグラムは個別の送信であり、実際には他のデータグラムに関連付けられていません。これが、TCPのソケットオプションがSOCK_STREAMである理由です。

これの明るい面は、TCPでは実際には簡単ではない個別の送信の感覚を得ることができるということです。

于 2010-02-10T20:23:30.177 に答える
0

私はあなたが正確に1つまたはゼロのデータグラムを取得すると信じています。しかし、現時点ではこれをバックアップすることはできません。おそらく他の誰かが良いリファレンスを提供することができますか?

編集:私はあなたが半分のデータグラムを受け取ることができないとかなり確信しています。データグラムがバッファに到着したか、到着していません。

于 2010-02-10T20:22:20.697 に答える