我對UDP的理解是,雖然MTU大小有限制,但如果數據報超過MTU,它將在IP層被分段,傳輸作爲單獨的數據包,然後在接收端進行重構。如果其中一個分段被丟棄,UDP層將丟棄整個數據報。如果一切都到達,IP層重新構造數據報,UDP應該將其作爲一個整體接收。然而,這並不是我所經歷的行爲。下面是一個簡單服務器循環.NET中的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}");
}
和經由netcat
發送數據的2999 bytes
如下
head -c 2999 /dev/urandom | nc -4u -w1 localhost 8999
服務器環路與大小1024
,1024
和951
字節的有效載荷接收三次。由於2*1024 + 951 = 2999
,似乎很明顯,我打算髮送的數據實際上是發送的,但UdpClient
正在接收它作爲三個不同的數據報。
這似乎與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不會分段。例如,TCP段,這與IP碎片完全不同。 –