2017-10-04 17 views
0

UDPの私の理解は、MTUサイズの制限がある間に、データグラムがMTUを超えると、IPレイヤーでフラグメント化され、別個のパケットとして受信し、次に受信側で再構成する。フラグメントの1つがドロップされた場合、UDPレイヤーはデータグラム全体をドロップします。すべてが到着すれば、IP層はデータグラムを再構成し、UDPはそれを全体として受け取るべきです。UDPの.Receive()は1kの部分で断片化されたデータグラムを返す

これは私が経験している動作ではありません。ここでは単純なサーバーループ

var udp = new UdpClient(port); 

while (true) { 
    IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0); 

    byte[] payload = udp.Receive(ref remote); 

    Console.WriteLine($"Received {payload.Length}, IP: {remote}"); 
} 

およびサーバーループはサイズ10241024951バイトのペイロードで三回受け

head -c 2999 /dev/urandom | nc -4u -w1 localhost 8999 

を以下のようnetcatを介してデータの2999 bytesを送信します。 2*1024 + 951 = 2999以降、私が送信しようとしていたデータが実際に送信されたのは明らかですが、UdpClientは3つの異なるデータグラムとして受信しています。

これはUDP層がデータグラム全体に作用するという事実と矛盾しているようです。 UDPで直接作業する場合は、独自のフラグメント再構成ロジックを実装する必要がありますか?あるいは、完全なデータグラムだけを受信する方法はありますか?

+0

私は専門家ではなく、デフォルトで[DontFragment](https://msdn.microsoft.com/en-us/library/system.net.sockets.udpclient.dontfragment(v = vs.110).aspx )が 'true'の場合、受信時にfalseに設定しようとします。しかし、ソケットを例にとると、データを受信するか、バッファがいっぱいになるまで(受信したと思われる)単純にブロックするので、データを結合する責任があると思います。[この質問](https://いくつかのヒントについては、「Stackoverflow.com/q/2319521/1997232」を参照してください。 – Sinatr

+0

フラグメンテーションは、レイヤ3のIPパケット上のルータによるものです。 TCPとUDPは断片化しません。たとえば、IPセグメント化とは完全に異なるTCPセグメントなどです。 –

答えて

0

あなたのUDPの理解は本当に正しいです。すべてのフラグメントが宛先に到着する限り、プロトコルは透過的にフラグメント化と再アセンブリを処理します。私は当初、headが1024バイトのチャンクでnetcatにデータを渡す可能性があると考えていましたが、そうではありません。

実際には反対のシナリオです。netcatは、1024バイトのブロックでstdinから読み取り、毎回新しいUDPパケットを生成しています。 netcatは、下層でどのようにパケット化されているかにほとんど関係のないデータの連続ストリームを処理するのに最適です。

詳細はthis StackOverflow questionをご覧ください。

関連する問題