跳轉到內容

序列埠程式設計/資料包的形成

來自 Wikibooks,開放的世界,開放的書籍

幾乎所有關於計算機之間通訊的想法都涉及“資料包”,尤其是在涉及到超過兩臺計算機的情況下。

這個想法非常類似於將支票放入信封中寄給電力公司。我們把要傳送給特定計算機的資料(“支票”)放在一個“信封”裡,這個信封包含特定計算機的地址。

資料包從一個前導碼開始,接著是頭資訊,然後是原始資料,最後用一些額外的位元組用於傳輸相關的錯誤檢測資訊——通常是一個 Fletcher-32 校驗和。我們將在下一章 序列埠程式設計/錯誤校正方法 中詳細討論如何處理這些錯誤檢測資訊。

電力公司的會計在收到支票後會扔掉信封。她已經知道她自己公司的地址了。但這是否意味著信封的“開銷”毫無用處?不。

同樣地,一旦一臺計算機收到資料包,它會立即扔掉前導碼。如果計算機看到資料包的地址是它自己,並且沒有錯誤,那麼它會丟棄包裝並保留資料。

頭資訊包含所有路由器和交換機用來將完整的資料包傳送到正確目標地址的目標地址資訊,就像紙質信封上寫著郵遞員用來將郵件傳送到正確目標地址的目標地址一樣。大多數協議使用一個頭資訊,像大多數紙質郵件信封一樣,還包括源地址和一些其他傳輸相關資訊。

不幸的是,資料包有幾十種略微不同、不相容的協議,因為人們選擇略微不同的方式來表示地址資訊和錯誤檢測資訊。

…… 不相容協議之間的閘道器 ……

資料包大小的權衡

[編輯 | 編輯原始碼]

協議設計人員根據許多權衡選擇最大和最小資料包大小。

  • 資料包應該“小”以防止一個發射機傳送一個長資料包來佔用網路。
  • 資料包應該“小”以便單個錯誤可以透過重新傳輸一個小資料包而不是一個大資料包來糾正。
  • 資料包應該“大”以便更多時間用於傳輸好資料,更少時間用於開銷(前導碼、頭資訊、尾資訊、後導碼和資料包間隙)。
  • 資料包頭資訊和尾部資訊應該很短,以減少開銷。
  • 尾部資訊應該包含一個大的錯誤檢測碼字欄位,因為一個較短的碼字更容易錯誤地接受一個錯誤嚴重的資料包(我們將在下一章 ../錯誤校正方法/ 中更詳細地討論錯誤檢測)。
  • 使資料包頭資訊稍微長一些,以便有意義的欄位落在位元組或字邊界上,而不是高度編碼的位欄位,使 CPU 更容易解釋它們,從而允許更低成本的網路硬體。
  • 使資料包頭資訊稍微長一些——而不是一個涵蓋整個資料包的單個錯誤檢測欄位,我們有一個用於頭資訊的錯誤檢測欄位,另一個用於資料的錯誤檢測欄位——允許一個節點立即拒絕一個在目標地址或長度欄位中出現位錯誤的資料包,避免不必要的處理。相同的 CRC 多項式用於兩者。這種只涵蓋頭資訊的“額外”CRC 在幾種檔案格式中使用[1]——它是 MPEG 音訊檔案格式的可選功能[2][3][4],gzip 格式的可選功能等等。
  • 固定大小的資料包——所有資料包都屬於幾個長度類別——不需要“長度”欄位,簡化緩衝區分配,但在您想傳送不是固定資料大小的精確倍數的資料時,會浪費“內部”資料空間來填充最後一個數據包。

資料包起始和透明度的權衡

[編輯 | 編輯原始碼]

不幸的是,任何通訊協議都無法擁有所有這些理想的功能

  • 透明度:資料通訊是透明的,並且是“8 位乾淨”的——(a) 任何可能的資料檔案都可以傳輸,(b) 檔案中的位元組序列始終被視為資料,而絕不會被誤解為其他東西,(c) 目標接收整個資料檔案,沒有錯誤,沒有新增或刪除任何內容。
  • 簡單複製:如果我們只是簡單地將資料從源盲目地複製到資料包的資料欄位中而不進行任何更改,那麼形成資料包最容易。
  • 唯一起始:資料包起始符號很容易識別,因為它是一個已知的常數字節,在頭資訊、頭資訊 CRC、資料有效負載或資料 CRC 中任何地方都不會出現。
  • 8 位:只使用 8 位位元組。

一些通訊協議會破壞透明度,需要在其他地方增加複雜性——需要更高的網路層來實現變通方法,例如 w:二進位制到文字編碼,否則會遇到神秘的錯誤,就像 w:時間無關轉義序列 那樣。

一些通訊協議會打破“8 位”——也就是說,除了 256 個可能的位元組之外,它們還有“額外的符號”。一些通訊協議只有少數幾個額外的非資料符號——例如用作 Hayes 轉義序列一部分的“長暫停”;用作 SDI-12 協議一部分的“長斷開”;4B5B 編碼、8b/10b 編碼中的“命令字元”或“控制符號”等。其他系統,例如 9 位協議,[5][6][7][8][9][10][11] 傳輸 9 位符號。通常資料包的第一個 9 位符號的高位設定為 1,喚醒所有節點;然後每個節點檢查資料包的目標地址,所有非目標節點都進入休眠狀態。資料包中的其餘資料(和 ACK 響應)以 9 位符號傳輸,高位清零到 0,有效地為 8 位值,休眠節點會忽略這些值。(這類似於 MIDI 訊息中所有資料位元組實際上都是 7 位值的方式;僅在 MIDI 訊息的第一個位元組中設定高位)。唉,一些 UART 使得傳送和接收這種 9 位字元變得很尷尬,[12][13] 困難或不可能。

一些通訊協議會打破“唯一開始”——也就是說,它們允許非唯一的開始資料包符號出現在其他地方——最常見的原因是我們正在傳送包含該位元組的檔案,而“簡單複製”會將該位元組放入資料有效負載中。當接收器第一次開啟,或當電纜拔掉後重新連線,或當噪聲破壞了原本應該作為真實開始資料包符號的內容時,接收器會錯誤地將該資料解釋為開始資料包。即使接收器通常會識別出出現問題(校驗和失敗),一次這樣的噪聲故障也可能導致許多資料包丟失,因為接收器在(錯誤地)將有效負載中的該資料位元組解釋為開始資料包,以及(錯誤地)將真實的開始資料包符號解釋為有效負載資料之間來回切換。更糟糕的是,這些常見問題可能會導致接收器丟失對字元開始和結束位置的跟蹤。早期的協議設計者認為,一旦同步丟失,就必須有一個唯一的開始資料包字元序列來重新獲得同步。[14] 之後的協議設計者設計了一些協議,例如基於 CRC 的幀,[15] 不僅打破了“唯一開始”——允許資料有效負載包含與開始資料包相同的位元組序列,支援簡單複製透明性——它們甚至不需要固定的不變的開始資料包字元序列。

為了保留“唯一開始”功能,許多通訊協議會打破“簡單複製”。這需要一些額外的軟體,並且每個資料包需要比簡單複製資料更多的時間——這在現代處理器中通常可以忽略不計。這種笨拙之處在於(a)確保整個過程——發射機將原始資料的塊編碼/轉義為資料包有效負載,該有效負載必須不包含開始資料包位元組,以及接收器將資料包有效負載解碼/解轉義為原始資料的塊——對所有可能的原始資料位元組序列都是完全透明的,即使這些位元組包含一個或多個開始資料包位元組,並且(b)由於編碼/轉義的有效負載資料不可避免地比原始資料需要更多位元組,我們必須確保我們即使在最壞的情況下也不溢位任何緩衝區,並且(c)與“簡單複製”不同,在“簡單複製”中,有效負載資料位的恆定位元率會導致原始資料位的相同恆定吞吐量,我們必須確保系統被設計為處理有效負載資料位元率或原始資料位元吞吐量或兩者的變化。透過使用一致開銷位元組填充(COBS),[16] 可以減少一些這種笨拙之處,而不是可變開銷位元組填充技術,例如 SLIP 使用的技術。

計算 CRC 並將其附加到資料包,*在*用 COBS 對原始資料和 CRC 進行編碼之前。 [17]

前導碼

[edit | edit source]

前導碼的兩種流行方法是

  • 第一個發射機傳送足夠的前導碼位,以便此跳躍的接收器鎖定。然後它傳送資料包。該接收器一旦知道它需要轉發資料包到另一個跳躍,就會在下一個跳躍上傳送一個新的完整大小的前導碼,後面跟著資料包。好處是,無論資料包跳躍多少次,相對較短的固定長度前導碼就足夠了。
  • 第一個發射機傳送一個長得多的前導碼,遠遠超出此跳躍的接收器鎖定所需的長度。然後它傳送資料包。該接收器,一旦檢測到前導碼,就會立即將每個傳入的位從另一個埠傳送出去,直到到達資料包的末尾。好處是中繼節點可以非常簡單,因為它們不需要儲存任何資料。前導碼消耗 (w:5-4-3 規則#前導碼消耗) 會使前導碼在每個跳躍後越來越短——丟失太多位,最終沒有足夠的前導碼位來鎖定,整個資料包都會丟失。

自動波特率檢測

[edit | edit source]


Clipboard

待辦事項
簡單介紹一下自動波特率檢測 (autobaud)。(序列程式設計書籍的哪個部分更適合討論 autobaud 實現?)




進一步閱讀

[edit | edit source]
  1. Andy McFadden。 "檔案格式設計"
  2. 維基百科:基本流
  3. Gabriel Bouvigne。 "MPEG 音訊層 I/II/III 幀頭"
  4. Predrag Supurovic。 "MPEG 音訊幀頭"
  5. uLan:9 位面向訊息的通訊協議,透過 RS-485 連結傳輸。
  6. Pavel Pisa。 "uLan RS-485 通訊驅動程式" "9 位面向訊息的通訊協議,透過 RS-485 連結傳輸。"
  7. Peter Gasparik。 "9 位資料傳輸格式"
  8. Stephen Byron Cooper。 "9 位序列協議".
  9. "使用 PC 的 UART 與 9 位協議"。1998 年。
  10. 維基百科:多點匯流排 (MDB) 是一種在許多自動售貨機中使用的 9 位協議。
  11. ParitySwitch_9BitProtocols:操縱奇偶校驗以模擬 9 位協議
  12. "使用 PC 的 UART 與 9 位協議"。電子設計。1998 年 12 月。
  13. Thomas Lochmatter。 "Linux 和 MARK/SPACE 奇偶校驗"。2010 年。
  14. J. Robinson。 RFC 935。 "可靠的鏈路層協議"。1985 年。引用:"一旦檢測到報頭錯誤,計數字段必須假定為無效,因此必須有一個唯一的字元序列來引入下一個報頭,以便接收器可以重新與傳送器同步。"
  15. 維基百科:基於 CRC 的幀
  16. "一致開銷位元組填充" 作者 Stuart Cheshire 和 Mary Baker,1999 年。
  17. Jason Sachs。 "救命,我的序列資料被幀化了:如何在只有流的情況下處理資料包"。2011 年。
“CMX-MicroNet 是第一個允許 TCP/IP
以及其他協議在小型處理器上原生執行的系統
... [包括] AVR、PIC 18、M16C。”
華夏公益教科書