2010-03-09 94 views
3

我已經閱讀過各種網站和教程,但我仍然困惑。如果消息大於IP MTU,則send()返回發送的字節。剩下的信息會發生什麼?我是否再次打電話send()並嘗試發送其餘消息?或者是IP層應該自動處理?TCP/UDP和以太網MTU碎片

回答

6

如果您使用的是TCP,那麼呈現給您的接口就是一串字節。您不必擔心字節流如何從連接的一端傳輸到另一端。你可以忽略IP層的MTU。實際上你可以完全忽略IP層。

當您撥打send()時,您計算機上的TCP協議棧將處理您推送到您的發送呼叫中的字節流所需的所有詳細信息,以便在連接另一端的recv()調用中出現。

有一兩件事要記住的是,與TCP你在處理流,這意味着,一個send()可能導致多個到達recv()電話和多個send()調用可能導致一個recv()呼叫到達的數據。你無法控制這一點。您正在處理一個字節流,每個調用recv()可以返回任意數量的字節從1到當前未完成的數字(允許足夠的緩衝區傳遞給recv()調用)。

由於評論者要求它;)

在大多數TCP協議棧send()是最有可能失敗,因爲TCP堆棧的緩衝區已滿,送一切(可能)的TCP窗口也充滿了和流量控制是這意味着堆棧無法發送任何數據,直到遠端確認某些數據,並且它不準備爲您代替緩衝。我還沒有碰到過一個TCP堆棧,將拒絕send()僅由於MTU的考慮,但我猜有些瘦了嵌入式系統的行爲可能這樣......

無論如何,如果send()回報比的字節數小於你提供了它,那麼你應該在某個時候重新發送剩餘的數據。經常send()會阻塞並等待,直到它可以發送所有數據,並且如果你已經將套接字設置爲非阻塞模式,那麼如果發送失敗,你可能不想立即重試發送,因爲你可能會結束在一個緊密的循環...

它可能會對你更具體的操作系統,你正在使用。

+5

+1,但是爲了完成,您還應該處理這個問題最感興趣的內容:如果'send'返回的值小於請求發送的字節(一個非常不可能的情況,因爲堆棧將嘗試處理它),如果必須的話,您有責任在稍後時間嘗試發送其餘數據。 – 2010-03-09 08:09:59

+0

真的不太可能嗎?因爲我看起來'send()'返回的值小於所請求的字節數,當請求的字節超過MTU時,所有的時間都發送出去。 – 2010-03-09 08:26:28

+0

Unix中的c。但你已經詳細回答了我的問題。非常感謝!! – 2010-03-09 09:33:51

0

如果數據包太大而無法傳輸網絡,則會發送ICMP碎片提示信號通知發件人以減小數據包大小並再次嘗試。

如果您使用TCP,這些都是您應該期待網絡層爲您照顧的所有細節。現代IP堆棧實際上在幕後進行計算,以找出路徑上最低的MTU,似乎已成爲某種黑色藝術。

WRT UDP你仍然可以期待堆棧碎片爲你,但實際上UDP的用例並不理想..根據你的應用程序,你可能通過明確理解路徑MTU來看到更好的性能。

...在send()問題上,一些堆棧的行爲不同,但WRT代碼的處理方式應該是相同的。假設你有100個字節發送... send()返回10個字節發送。您需要使用剩餘的90個字節繼續呼叫發送,直到它全部推出電線以發送整個消息。

在Windows平臺上使用阻塞套接字send()將在所有內容發送完成後立即返回。在其他平臺上.. Linux等您需要不斷髮送更多的數據來推送數據。