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}");
}
およびサーバーループはサイズ1024
、1024
と951
バイトのペイロードで三回受け
head -c 2999 /dev/urandom | nc -4u -w1 localhost 8999
を以下のようnetcat
を介してデータの2999 bytes
を送信します。 2*1024 + 951 = 2999
以降、私が送信しようとしていたデータが実際に送信されたのは明らかですが、UdpClient
は3つの異なるデータグラムとして受信しています。
これはUDP層がデータグラム全体に作用するという事実と矛盾しているようです。 UDPで直接作業する場合は、独自のフラグメント再構成ロジックを実装する必要がありますか?あるいは、完全なデータグラムだけを受信する方法はありますか?
私は専門家ではなく、デフォルトで[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
フラグメンテーションは、レイヤ3のIPパケット上のルータによるものです。 TCPとUDPは断片化しません。たとえば、IPセグメント化とは完全に異なるTCPセグメントなどです。 –