9.2. 分層協定

把一張影格從相機傳送到另一座城市的伺服器,意味著要同時解決好幾個問題。電氣訊號必須先通過第一段線路。線上的位元組必須穿越本地交換器找到去路。本地網路必須把訊息交給介於它與網際網路其餘部分之間的任何裝置。順利完成這趟旅程的封包必須按順序重新組裝。接收端必須知道要把它們交給自己的哪一支程式。而這些位元組本身也必須具有兩端都認同的意義。

想在單一段程式碼中解決上述全部問題會難以管理。標準的做法是把工作切分成多個。每一層解決一個定義明確的問題,並向其上層提供一項簡單的服務。一支程式永遠只與緊鄰其下的那一層對話;再下面的各層則是看不見的。

由下而上標示為五個方框的垂直堆疊: 實體層、連結層、網路層、 傳輸層、應用層。右側有一個箭頭 向上指,標示為「我們建構的部分」。 左側有一個箭頭向下指, 標示為「所提供的部分」。

網路堆疊的每一層解決一個問題,並向上一層交付一個乾淨的抽象。

9.2.1. 五個層

以下名稱是本節其餘部分所使用的。它們來自網路設計所圍繞的標準模型。各層之間的確切邊界有時模糊不清,但每一層所扮演的角色是穩定的。

實體層。 在同一條線路或無線電上的兩個裝置之間移動位元。電壓位準、光脈衝、RF 調變。相機在此的工作大多只是插上正確的纜線或加入正確的無線網路;其餘的交由晶片完成。

連結層。 在共用同一個本地網段的兩個裝置之間移動影格(小塊位元組)。它加上硬體位址,讓每個影格都能導向某個特定的相鄰裝置。Ethernet 與 Wi-Fi 是相機實務上會遇到的兩種連結技術。

網路層。網際網路上任意兩個裝置之間移動封包,而不僅限於同一個本地網段。它加上一個軟體層級的位址,以與裝置所在纜線無關的方式識別某個主機,並加上一個路由機制,讓封包從一個本地網段跳到下一個,直到抵達目的地。這是相機的 Python 程式碼開始有發言權的第一層。

傳輸層。 位於封包之上,提供兩台主機上的程式之間的傳遞,而不僅是主機本身之間。常見的有兩種型態:一種傳遞已連線、有序的位元組串流(多數流量的主力),另一種傳遞各自獨立傳送的自含訊息(在低開銷比可靠保證更重要時使用)。它加上連接埠號,讓同一台主機上的多支程式能夠平行進行對話。

應用層。 傳輸層之上的一切:賦予位元組意義的協定。網頁瀏覽器用來載入頁面所說的那些協定 -- 以及讀者每天早已使用的幾乎所有其他網際網路服務背後的協定 -- 都位於此層。本教學會深入介紹傳輸層;本層則另有專屬的後續章節。

9.2.2. 各層在執行時如何堆疊

當相機透過網路傳送位元組時,每一層都會在資料前面加上自己的標頭,就像把一個信封層層套進另一個信封裡:

  • 應用程式的位元組最先放入。

  • 傳輸層用一個小標頭把它們包起來,說明它們屬於哪一支程式(連接埠號)。

  • 網路層再用一個標頭把那個包起來,說明它們要送往哪一台主機(軟體層級的位址)。

  • 連結層再用一個標頭把那個包起來,說明本地網段上接下來要交給哪一個裝置(硬體位址)。

  • 實體層把整個包裹轉換成線上的位元。

在另一端,每一層剝去自己的標頭,把其餘部分往上交。接收端的應用程式拿回它的位元組,渾然不知網路層、連結層與實體層曾經存在過。

正是這種層層巢狀的關係,本教學才採用由下而上的方式講解。理解下層所做的事,會讓上層感覺理所當然。最底下兩層各以單一頁面介紹,因為從 Python 幾乎沒有什麼可設定的。從網路層往上,隨著 Python 的角色越來越重要,步調也會放慢。