Tcp

我可以相信負載為 255 字節的 TCP 段將在單個乙太網幀中傳送嗎?

  • March 3, 2016

我正在編寫一些伺服器軟體來升級電子設備上的韌體。這是一項棘手的任務,因為目前這些設備在安裝之前沒有足夠的記憶體來保存完整的韌體。結果,我的伺服器會將設備切換到引導載入程序模式,並指示引導載入程序做什麼,通過網路發送指令和韌體數據。可以想像,這有一些潛在的巨大缺點。

我現在關心的是,我發送的單個 TCP 段是否會被分成多個乙太網幀?

由於引導載入程序的性質,我可以在 TCP 段中發送的最大有效負載為 255 字節。

從 Wireshark 中抓取數據包來看,包含我的 TCP 段之一的幀的幀大小似乎是 309 字節(2,472 位),完全在乙太網幀上的維基百科頁面允許的範圍內:

乙太網類型 2 幀格式

我目前正在嘗試處理如果與設備的連接被切斷會發生什麼。就像現在一樣,我可以毫無困難地重新建立與設備的連接,但我想確定的是重新建立連接後會發生什麼。

如果我可以確定每條指令將始終包含在單個乙太網幀中,並且因此,要麼傳遞要麼不傳遞,那麼快樂的日子!我可以查看發送的最後一條指令並弄清楚接下來要做什麼。

但是,如果有可能將指令拆分為兩個乙太網幀,那麼我的問題就更大了。我認為它不應該發生,但有時在我測試時看起來會發生這種情況。

假設我已經發出了一個寫命令,並且引導載入程序正在等待數據寫入,我發送了 255 字節的 TCP 段,它被分成兩個乙太網幀。第一幀被傳遞,但第二幀沒有。現在,當我重新連接時,我必須弄清楚引導載入程序已經收到了多少字節,這意味著我需要推送虛擬數據並監聽響應。如果可能的話,我真的很想避免這種情況。

從這個執行緒中的評論來看,小於 576 字節(4,608 位)的 IP 數據包似乎不會被拆分。我可以安全地假設情況總是如此嗎?

實際上,如果它被拆分,那麼 WiFi 模組不應該在重新組裝之前傳遞 TCP 段,不是嗎?如果連接失去,它將被丟棄。

一般來說,很難控制數據包是否被拆分。實際上,您需要深入了解堆棧 - 諸如將 TCP 解除安裝到硬體之類的事情也可能會妨礙並創建針對傳輸進行優化的數據包。

但是你說的是 TCP 連接——所以如果你的連接有一個短暫的中斷,應該不會有任何問題。如果單個 TCP 數據包被拆分為多個乙太網數據包,並且您的連接在單個幀的傳輸之間斷開(短時間內),TCP 將重試傳輸數據包(這是協議的一部分)。

有一個更長的/檢測到的斷開連接,一個更大的問題將是事實,你不能在不重新建立新連接的情況下繼續發送(這需要你的設備支持) - 設置一個新的套接字並發送到同一個任何預設堆棧都可能不支持沒有 TCP syn/ack 的遠端主機。

關於您想要的目標(如果可能),我建議在韌體升級期間採用適當的方法來處理中斷(例如雙啟動)。

如果這是不可能的,並且您沒有實現自己的 TCP/IP 堆棧,我只能建議禁用伺服器上的任何硬體加速(以防止硬體重新組裝數據包)並在套接字連接上禁用nagle 算法。

引用自:https://serverfault.com/questions/761329