2017-10-04 53 views
0

我對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 

服務器環路與大小10241024951字節的有效載荷接收三次。由於2*1024 + 951 = 2999,似乎很明顯,我打算髮送的數據實際上是發送的,但UdpClient正在接收它作爲三個不同的數據報。

這似乎與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不會分段。例如,TCP段,這與IP碎片完全不同。 –

回答

0

你對UDP的理解確實是對的。只要所有片段到達目的地,協議就會透明地爲你處理分片和重組。我最初以爲head可能會將您的數據以1024字節的塊傳遞給netcat,但情況並非如此。

實際上是相反的情況:在您的系統netcat正在從stdin以1024字節的塊讀取並且每次生成一個新的UDP數據包。看起來netcat最適合用於處理連續的數據流,這些數據流對低層分組方式基本無關緊要。

更多信息請見this StackOverflow question