Download presentation
Presentation is loading. Please wait.
1
第 12 章 UDP 與 TCP
2
本章提要 12-1 UDP 12-2 TCP 12-3 TCP 傳送機制 12-4 TCP 連線 12-5 TCP 封包
3
前言 先前第 8 章至第 11章已陸續介紹了網路層相關的協定與功能。本章將要介紹傳輸層的協定。
在 DoD 模型中, 傳輸層位於網路層與應用層之間, 主要的功能是負責應用程式之間的通訊。舉凡連接埠管理、流量控制、錯誤處理, 與資料重送皆是傳輸層的工作。 本章將介紹 TCP/IP 協定組合在傳輸層的兩個協定:UDP 與 TCP, 藉此說明傳輸層的各項功能。
4
12-1 UDP UDP (User Datagram Protocol) 是一個相當陽春的協定, 僅提供連接埠 (Port)處理的功能。UDP 具有以下特性: UDP 表頭可記錄封包來源端與目的端的連接埠資訊, 讓封包能夠正確地送達目的端的應用程式。
5
UDP 非連接式 (Connectionless) 的傳送特性。UDP 與 IP 雖然是在不同層運作, 但都是以非連接式的方式來傳送封包 (參見 8-1 節)。由於此特性, 使得 UDP 的傳送過程較為單純, 但是相對地可靠性較差。在傳送過程中若發生問題, UDP 並不具有確認、重送等機制, 而是必須仰賴上層 (應用層) 的協定來處理這些問題。
6
UDP 與 TCP 相比, 由於 UDP 僅提供基本傳輸層的功能, 因此在應用上不若 TCP 廣泛。使用 UDP 的應用程式, 通常是基於以下的考量: 為了要降低對電腦資源的需求。以 DNS 服務為例, 由於可能要面對大量用戶端的詢問 (請參考第 13 章), 若是使用 TCP 可能會耗費許多電腦資源, 因此使用資源需求較低的 UDP 。
7
UDP 應用程式本身已提供資料完整性的檢查機制, 因此毋須仰賴傳輸層的協定來執行此工作。此外, 若應用程式傳輸的並非關鍵性的資料, 例如:路由器會週期性地交換路由資訊, 若這次傳送失敗, 下次仍有機會將資訊重送。在這種情況下, 也會使用 UDP 作為傳輸層的協定。
8
UDP 要使用多點傳送 (Multicast) 或廣播傳送 (Broadcast) 等一對多的傳送方式時, 必須使用 UDP。這是因為使用連接式 (Connection-Oriented) 傳送方式的 TCP(參見下一節), 僅限於一對一的傳送方式。
9
連接埠 UDP 最重要的功能是管理連接埠。從先前介紹 IP 的章節中, 我們已經知道 IP 的功能是要將封包正確地傳送至目的地。不過, 當 IP 封包送達目的地時, 接下來便立即面臨一個問題, 電腦上可能同時執行多個應用程式, 例如:使用者同時開啟 Internet Explorer 與 Outlook Express, 那麼收到的 IP 封包應該送至哪一個應用程式呢?UDP 便是利用連接埠來解決上述的問題。
10
什麼是連接埠? 連接埠的英文為 Port, 但它並非像是電腦平行埠或序列埠等實體的接頭, 而是屬於一種邏輯上的概念。每一部使用 TCP/IP 的電腦, 都會有許多連接埠, 並使用編號加以區分。應用程式若經由 TCP/IP 存取資料, 就必須獨佔一個連接埠編號。 因此, 當主機收到 IP 封包後, 可以藉由連接埠編號, 判斷要將封包送給哪一個應用程式來處理。
11
什麼是連接埠? IP 位址與連接埠編號兩者合起來稱為 Socket Address (簡稱為 Socket), 可用來定義 IP 封包最後送達的終點, 亦即目的地應用程式。以現實生活為例, IP 位址就好比是某棟建築物的地址, 而連接埠編號就好比是建築物內的房間或窗口的號碼。假設您要去郵政總局洽公, 若只知道其地址為『台北市忠孝西路1段114號』,您只能找到該棟大樓。
12
什麼是連接埠? 但是, 郵政總局裏面可能有許多個窗口, 因此, 只知道地址是不夠的, 您還必須知道要去哪一個窗口辦理。如果您能夠事先知道『台北市忠孝西路1段114號第 80 號窗口』這樣子的資訊, 便能迅速正確地找到要洽公的單位。 IP 位址與連接埠編號也是同樣的道理。一部電腦或許只有一個 IP 位址, 但可能同時執行許多個應用程式。
13
什麼是連接埠? 應用程式彼此之間以連接埠編號來區分。當電腦收到 IP 封包時, 便可根據其連接埠編號 (記錄在傳輸層協定的表頭中), 判斷要交由哪個應用程式來處理。 當然, 每個封包除了要記錄目的端的連接埠編號外, 也會記錄來源端的連接埠編號, 以便相互傳遞封包。所有與連接埠相關的工作, 都是由傳輸層的協定來負責。
14
連接埠編號的原則 連接埠編號為 16 Bits 長度的數字, 可從 0 至 65535。按照 IANA (Internet Assigned Numbers Authority) 的規定, 0 ~ 1023 的連接埠編號稱為『Well-Known』(廣為人知的意思) 連接埠, 主要給提供服務的應用程式使用。凡是在 IANA 登記有案的應用程式, 都會分配到一個介於 0 ~ 1023 之間的固定連接埠編號。例如:DNS 為 53, 代表 DNS 服務都應使用 53 的連接埠編號。
15
連接埠編號的原則 至於 1024 ~ 的連接埠編號則稱為『Registered』連接埠, 此部份提供給各軟體公司向 IANA 註冊,以保留給特定的應用程式或服務使用。像 Shockwave 這個網際網路上所用的動畫技術, 就是用 1626 這個註冊的連接埠。至於 ~ 則稱為『Dynamic』(動態) 連接埠, 由用戶端自行使用。例如:用戶端使用 Internet Explorer 連上網站時, 系統會隨機分配一個連接埠編號供 Internet Explorer 使用。
16
連接埠編號的原則 以下列出一些常見的 Well-Known 連接埠供讀者參考:
17
連接埠編號的原則 為什麼伺服器應用程式必須使用 Well-Known 連接埠, 而用戶端應用程式可使用 Registered / Dynamic 連接埠呢? 這是因為在一般網路的應用中, 兩部電腦若要互傳封包, 一開始都是由用戶端主動送出封包給伺服器。換言之用戶端必須在送出封包前便知道伺服器應用程式的連接埠編號。
18
連接埠編號的原則 因此伺服器應用程式所使用的連接埠編號勢必遵循一套大家公認的準則, 例如:Telnet 服務應該固定使用編號為 23 的連接埠、Web 服務應該固定使用編號為 80 的連接埠等等。這些準則即形成了 Well-Known 的連接埠。
19
連接埠編號的原則 至於用戶端應用程式的連接埠編號, 由於伺服器收到來自用戶端的封包後, 從表頭中便可得知用戶端應用程式的連接埠編號。因此, 用戶端應用程式不必像伺服器一樣必須硬性規定連接埠編號。
20
使用自訂的伺服器連接埠編號 Well-Known 連接埠其實有點類似『約定俗成』的意思, 並不具有強制性質。換言之, 您可以將 Web 服務的連接埠編號設為 2001, 在設定上不會有任何問題。麻煩的是, 您必須讓每個使用者知道, 該 Web 服務使用的連接埠編號為 2001, 而非預設的 80。 當然, 如果您這部伺服器只服務少數特定人士, 而不想開放給一般大眾存取, 使用自訂的連接埠編號, 反而是一種保護方法。
21
UDP 封包的結構 UDP 封包是由以下兩部份所組成:
22
UDP 封包的結構 UDP 表頭:主要是用來記錄來源端與目的端應用程式所用的連接埠編號。
UDP 資料:載送應用層 (Application Layer) 的資訊。這部份可視為 UDP Payload, 不過一般都稱為 UDP Data 或 UDP Message, 在此我們稱為『UDP資料』。
23
UDP 封包的結構 UDP 位於網路層與應用層之間, 對上可接受應用層協定所交付的資訊, 形成UDP 資料;對下則是將整個 UDP 封包交付給 IP (網路層的協定), 成為 IP Payload。 UDP 表頭長度固定為 8 Bytes, 其中包含了 4 個長度為 16 位元的欄位:
24
UDP 封包的結構 來源連接埠編號 目的連接埠編號
用來記錄來源端應用程式所用的連接埠編號。若目的端應用程式收到封包後必須回覆時, 由本欄位可知來源端應用程式所用的連接埠編號。 目的連接埠編號 用來記錄目的端應用程式所用的連接埠編號。這個欄位可說是 UDP 表頭中最重要的資訊。
25
UDP 封包的結構 封包長度 用來記錄 UDP 封包的總長度, 以 Byte 為單位。此欄位值最小為 8, 也就是整個封包只有 UDP 表頭, 沒有任何 UDP 資料;最大值則受限於 IP Payload 的長度。 錯誤檢查碼 用來記錄 UDP 封包的錯誤檢查碼。UDP 不一定要執行錯誤檢查, 若是為了降低運算資源的需求等, 可以不用執行錯誤檢查, 此時本欄位填入 0 即可。
26
錯誤檢查碼計算方式 UDP 錯誤檢查碼的檢查範圍有些複雜, 除了 UDP 表頭與 UDP 資料, 計算錯誤檢查碼時, 會另外產生『Pseudo Header』 (假表頭), 它包括以下的欄位: 來源位址:IP 表頭中來源端的 IP 位址。 目的位址:IP 表頭中目的端的 IP 位址。 未用欄位:長度為 8 Bits, 填入 0。
27
錯誤檢查碼計算方式 上層協定:IP 表頭中紀錄上層協定的欄位。 封包長度:UDP 表頭中的封包長度欄位。
此外, 錯誤檢查碼的計算範圍必須是 2 Bytes 的倍數。因此, Pseudo Header 加上 UDP 封包的總長度若非 2 Bytes 的倍數, 則會在最後面加上 1 Byte 的 Padding,使之成為 2 Bytes 的倍數。
28
錯誤檢查碼計算方式 讀者一定很好奇, 為什麼在計算錯誤檢查碼時, 需要加上 Pseudo Header 呢?Pseudo Header 的功能主要是為了要檢查 UDP 封包是否送達正確的終點。首先我們來看看在 UDP 封包傳送過程中, 計算錯誤檢查碼的步驟: 在來源端電腦中, UDP 計算錯誤檢查碼時, 會暫時將 Pseudo Header 加至 UDP封包:
29
錯誤檢查碼計算方式 在計算完錯誤檢查碼後立即將 Pseudo Header 與 Padding 移除。因此, Pseudo Header 與 Padding 不會成為 IP Payload, 當然也不會傳送到目的端。 目的端收到 UDP 封包後, 會從 IP 表頭讀取相關資訊, 再度產生 Pseudo Header與 Padding, 而後計算錯誤檢查碼, 然後與 UDP 表頭中的錯誤檢查碼比對。
30
錯誤檢查碼計算方式 假設 UDP 封包的傳送過程中出現錯誤, 例如:原始封包目的位址為 , 目的連接埠編號為 80, 但是陰錯陽差而使得 這部電腦連接埠編號為 80 的 Web Server 收到此封包, 這時在比對錯誤檢查碼時便會出現不一致的現象, 目的端的 UDP 便會將此封包丟棄。
31
錯誤檢查碼計算方式 UDP 的錯誤檢查碼可視為雙重保險的機制。當封包在傳遞中發生錯誤, 而位於UDP 下的各層協定都沒有找出此錯誤時, Pseudo Header 提供了一道額外的防線。
32
UDP 如何取得 IP 表頭資訊? Pseudo Header 中來源位址、目的位址與上層協定欄位的資訊是由 IP 層提供(參見 8-1 節)。讀者一定會覺得有些奇怪, UDP 如何取得 IP 層的資訊?事實上, RFC 規定UDP / IP之間的介面必須有相互交換資訊的能力。因此, UDP 在計算 Checksum 時, 便可透過 UDP / IP 介面得到上述 3 個欄位的資訊。相同的情況也發生在 TCP 與 IP 之間的介面。
33
擷取 UDP 封包 接下來我們就利用 NetAnalyzer, 實際擷取 UDP 封包, 看看它到底長什麼樣子。以下是在瀏覽器連上 Web Site 前, 執行名稱解析 (詳見第13章) 時所擷取的DNS 封包:
34
擷取 UDP 封包
35
擷取 UDP 封包 來源端連接埠編號。3008 屬於 Dynamic 的連接埠編號。
目的端連接埠編號。53 為 DNS 的 Well-Know連接埠編號。 UDP 封包的長度。 錯誤檢查碼。 這是 UDP 資料內容, 從 Name 欄位可知此為查詢 tw.lycosasia.com 的 IP 位址的 DNS Query 封包 (詳見第 13 章)。
36
12-2 TCP 與 UDP 相較, TCP (Transmission Control Protocol) 提供了較多的功能, 但相對地表頭欄位與運作機制也較為複雜。本節首先介紹 TCP 的特性, 至於傳送機制、連線過程和表頭結構則在後續各節中說明。
37
TCP TCP 為傳輸層的協定, 與 UDP 同樣地具備處理連接埠的功能。有關連接埠的功能, 本節不再贅述。除了連接埠功能外, 更重要的是 TCP 提供了一種『可靠』的傳送機制。什麼是『可靠』的傳送機制?為什麼重要?在探討這些問題之前, 讓我們先回顧一下 IP 、乙太網路這些底層協定的特性。
38
TCP 無論是網路層的 IP, 或是鏈結層的乙太網路, 來源端在傳送封包時, 完全不知道目的端的狀況。目的端可能過於忙碌而無暇處理封包、可能收到已經損毀的封包、可能根本就收不到封包...這些狀況來源端都無從得知, 當然也就無法因應, 只能『盲目地』不斷將封包送完為止。
39
TCP 這樣子的傳輸方式可稱之為『不可靠』的傳送機制。乍聽之下此種方式好像一無是處, 其實不然。『不可靠』的傳送機制較為簡單, 因此在實作上比較適合底層的協定。既然底層協定『不可靠』 , 責任就落到上層協定囉。這時候有兩種解決之道:
40
TCP 傳輸層仍舊維持『不可靠』的特性 (例如:UDP), 而讓應用層的應用程式一肩扛起所有的工作。這種方式的缺點就是, 程式設計師在撰寫應用程式時非常麻煩, 必須實作各種錯誤檢查、修正的功能。 傳輸層使用『可靠』的傳輸方式 (例如:TCP), 讓應用層的應用程式簡單化, 程式設計師也能夠準時下班。
41
TCP 讀者可以理解為什麼 TCP 的應用遠較 UDP 廣泛了吧。那麼, 所謂『可靠』的傳輸方式, 到底該可靠到什麼程度呢?
42
TCP 資料確認與重送 當 TCP 來源端在傳送資料時, 透過與目的端的相互溝通, 可以確認目的端已收到送出的資料。如果目的端未收到某一部份資料, 來源端便可利用重送的機制,重新傳送該資料。 流量控制 由於軟、硬體上的差異, 每一部電腦處理資料的速度各不相同, 因此 TCP 具有流量控制的功能, 能夠視情況調整資料傳輸的速度, 儘量減少資料流失的狀況。
43
TCP 連線導向 TCP 為連接式 (Connection-Oriented) 的通訊協定。所謂『連接式』, 是指應用程式利用 TCP 傳輸資料時, 首先必須建立 TCP 連線, 彼此協調必要的參數 (用於上述資料重送與確認、流量控制等功能), 然後以連線為基礎來傳送資料。
44
12-3 TCP 傳送機制 TCP 的傳送機制較為複雜, 因此, 在介紹 TCP 連線之前, 有必要先了解這些機制。本節首先會以一個簡單的模型讓讀者了解 TCP 傳送的基本方式, 然後以此為基礎, 逐步說明 TCP 的各項傳送機制。
45
12-3-1 確認與重送 既然說 TCP 使用『可靠』的傳送機制。那麼這個機制的基本原理到底為何?
簡而言之, 就是『確認與重送』。就好比是上司對部屬講話時, 部屬必須藉由唯唯諾諾或不斷點頭等方式, 表示自己已確實聽到講話內容。如果部屬完全沒有反應,上司必須合理懷疑部屬沒有聽到, 因此會重講一遍, 或把部屬訓飭一頓, 讓他集中精神。
46
確認與重送 TCP 也是運用同樣的道理來傳送資料。以下我們就利用一個簡單的模型, 解釋如何以『確認與重送』的機制, 可靠地傳送封包。假設 A 要傳送封包給 B, 透過下列步驟, A 便可確認 B 已收到封包: A 首先傳送 Packet 1 封包給 B, 然後開始計時, 並等待 B 的回應。
47
確認與重送 B 收到 Packet 1 封包後, 傳送 ACK 1 封包給 A。ACK 1 封包的內容為『我已經收到 Packet 1 封包了』。 A 如果在預定的時間內收到 ACK 1 封包, 便可確認 Packet 1 正常地到達目的地。接著即可傳送 Packet 2 封包給 B, 然後開始計時, 並等待 B 的回應。 B 收到 Packet 2 封包後, 傳送 ACK 2 封包給 A。ACK 2 封包的內容為『我已經收到 Packet 2 封包了』。
48
確認與重送
49
確認與重送 透過上述步驟, A 可以確認 B 已收到 Packet 1、Packet 2 等封包。
若在封包傳送的過程中出現錯誤, 例如:Packet 2 在傳送途中失蹤了, 此時 B 便不會發出 ACK 2 給 A。A在預訂的時間內沒有收到 ACK 2, 即判定 B 未收到 Packet 2, 因此便重新傳送 Packet 2 給 B。
50
確認與重送
51
確認與重送 重送封包其實就是一種錯誤處理的機制。換言之, 在 TCP 傳送過程中, 即使發生錯誤, 仍可藉由重送封包的方式來補救, 如此才能維持資料的正確性與完整性。
52
Sliding Window 上述封包傳送的過程, 雖然具有確認與重送的功能, 但在效能方面卻造成很大的問題。這是因為當 A 每傳送出去一個封包後, 便只能癡癡地等, 一直等到收到對應的 ACK 封包後, 才能傳送下一個封包。如果真的實作出這樣子的協定, 在整個傳送過程中, 絕大部份時間勢必都浪費在等待 ACK 封包。
53
Sliding Window 為了解決這個問題, 就有聰明人想出一種叫做『Sliding Window』的技術。
『Sliding Window』雖然有『Window』這個字眼, 不過和微軟的 Windows 作業系統完全無關。為什麼會叫做『Sliding Window』呢? 因為它的運作概念就像是一個可滑動的窗口!
54
Sliding Window 讀者可以想像用一張中間挖空的厚紙板, 挖空的部份即是所謂的 Window, 我們可從挖空的部份去檢視來源端傳送出去的封包。 接著仍舊以 A 為來源端、B 為目的端, 說明如何利用 Sliding Window 的機制來傳送封包。在傳送一開始時, A的 Sliding Window 應該是像這個樣子:
55
Sliding Window
56
Sliding Window A 首先將 Window 內看得見的所有封包送出, 也就是送出 Packet 1、Packet2 和 Packet 3 封包, 然後各別對這些封包計時, 並等候 B 回應。 B 收到封包後, 會依封包編號送回對應的 ACK 封包給 A。例如:B 收到Packet 1, 便會回應 ACK 1 封包給 A。假設一切正常, A 首先會收到 ACK 1 封包,接著便執行以下動作:
57
Sliding Window 將 Packet 1 標示為『完成』。
58
Sliding Window 將 Sliding Window 往右滑動 1 格。
59
Sliding Window 將新進入 Sliding Window 的 Packet 4 (位於 Window 的最右邊) 送出。
接下來當 A 收到 ACK 2 與 ACK 3封包時, 仍是重複上述步驟。整個過程有如右圖所示:
60
Sliding Window
61
Sliding Window 透過 Sliding Window 的方式, A 可以迅速送出多個封包。相較於每送出一個封包便要等待對應的 ACK 封包, Sliding Window 顯然具有較佳的傳輸效率。
62
12-3-3 Send / Receive Window
先前說明 Sliding Window 所舉的例子中, 僅 A 具有 Sliding Window。不過,實際上 TCP 的來源端與目的端會有各自的 Sliding Window。為了方便區分, 我們將來源端的 Sliding Window 稱為 Send Window (傳送窗口), 目的端的 Sliding Window 稱為 Receive Window (接收窗口)。
63
Send / Receive Window Receive Window 的功能是什麼呢?以先前的例子而言, 當 A 傳送封包給 B時, 由於封包不見得會按照原有的順序到達 B, 因此 B 勢必要藉由 Receive Window,記錄連續收到的封包與沒有連續收到的封包。B 只會將連續收到的封包轉交給上層應用程式;同樣地, 也只會針對連續收到的封包發出 ACK 。
64
Send / Receive Window 以下例而言, 第 1 ~ 7 個封包屬於連續收到的封包。由於第 8、9 和第 14 個封包尚未收到, 所以後續第 10 ~ 13 與第 15 ~ 16 個收到的封包, 皆屬於沒有連續收到的封包。
65
Send / Receive Window Receive Window 會隨著連續性的封包移動。我們仍舊以 A 為來源端、B 為目的端, 在傳送一開始時, B 的 Receive Window 應該是像這個樣子:
66
Send / Receive Window
67
Send / Receive Window 當 B 收到 A 送來的封包時, 會有下列動作:
將收到的封包加以標示。例如:收到 Packet 1, 便將 Packet 1 標示為『收到』。 如果收到的封包位於 Window 的最左邊, 則發出對應的 ACK 封包, 並將 Receive Window 往右滑動 1 格。如果 Window 最左邊的封包也已經標示為『收到』 ,則再往右 1 格, 直到最 Window 最左邊的是尚未標示為『收到』的封包。
68
Send / Receive Window 假設 B 是以 Packet 3、Packet 1、Packet 2 的順序收到封包, 則 B 的 Receive Window 會進行如下的動作: B 最先收到 Packet 3, 所以將 Packet 3 標示為『收到』。由於 Packet 3 並非Window 最左邊的封包, 因此不必送出 ACK, 也不用移動 Receive Window。
69
Send / Receive Window
70
Send / Receive Window 收到 Packet 1, 這時候 B 除了將 Packet 1 標示為『收到』外, 因為 Packet 1 為W i n d o w 最左邊的封包, 因此必須送出 A C K 1, 並將 R e c e i v e Window 往右移動 1 格。
71
Send / Receive Window
72
Send / Receive Window 收到 Packet 2, 這時候 B 將 Packet 2 標示為『收到』後, 送出 ACK 2 並將 Receive Window 往右移動 1 格。但是 Packet 2 後面的 Packet 3 也已經標示為『收到』, 因此又送出 ACK 3, 然後將 Receive Window 再往右移動 1 格。
73
Send / Receive Window
74
Send / Receive Window 下圖總結 A 的 Send Window 與 B 的 Receive Window 在上述步驟中的變化:
75
Send / Receive Window
76
Send / Receive Window 在 Receive Window 中, 當封包從 Window 最左邊出去後 (也就是已送出對應的 ACK), 接著應該就交給上層應用程式了。不過, 為了提高效能, B 不會將這些封包逐一轉交給上層應用程式, 而是先將它們放在緩衝區 (Buffer), 等緩衝區滿了再一次送給應用程式。
77
Window Size 與流量控制 TCP 具有一項重要的功能, 便是流量控制 (Flow Control), 亦即 TCP 能夠視情況需要, 隨時調整資料傳送速度。流量控制主要是靠 S l i d i n g Window 的大小 (稱為 Window Size) 來調整: 當 Window Size 變小時, 流量也會變慢。當 Window Size 為 1 個封包大小時,封包傳送的方式就有如 節所介紹的『確認與重送』模型, 每送 1 個封包就要等待確認, 傳輸效率極差。
78
Window Size 與流量控制 當 Window Size 變大時, 可連續傳送多個封包, 流量也會變快。但是相對地, 較大的 Window 會耗費較多的電腦資源。 在決定 Window Size 時, 必須衡量上述兩種因素, 從中取得平衡點。例如:當電腦因為配備不夠好, 或是過份忙碌時, 會儘量使用較小的 Window Size 來傳輸資訊。
79
Window Size 與流量控制 那麼, Window Size 是由誰來決定的呢?答案是目的端。以先前的例子來說, B 根據本身的狀況決定 Receive Window 大小, 然後將此資訊放在 ACK 封包中通知 A, A 再將 Send Window 調整為相同的大小。
80
Window Size 與流量控制 在整個傳送過程中, B 的 Receive Window 大小會隨著客觀條件不斷變化, 例如:B 電腦太過忙碌, 來不及處理 A 傳送過來的資料時, 便會將 Receive Window變小。B 藉由 ACK 封包, 可即時通知 A 調整傳送封包的速度。
81
以 Byte 為單位 我們在先前的模型中, 為了方便說明都是以封包為單位。不過, 實際上 TCP在處理資料時皆是以 Byte 為單位, 將 TCP Payload 視為一個個 Byte 串連而成的Bytes Stream。以下仍以 A 傳送資料給 B 為例, 說明 TCP 如何以 Byte 為單位來處理資料。
82
以 Byte 為單位 序號 (Sequence Number) 回應序號 (Acknowledge Number)
定義 Window 的邊界
83
序號 (Sequence Number) 首先要澄清一個觀念:TCP 封包內所記錄的序號 (Sequence Number), 是指 TCP Payload 的第 1 個 Byte 的編號, 不是封包本身的編號。在連線一開始, A 會隨機選取一個數字作為 Initial Sequence Number (ISN, 初始序號), 並以 1 個同步封包 (詳見後文) 通知 B, 俟獲得 B 回覆 ACK 之後, A 開始將 TCP Payload 打包、編號送出。
84
序號 (Sequence Number) 但是所編的第 1 個號碼不是 ISN, 而是 ISN+1。(雖然同步封包只有表頭、沒有 Payload, 照理說不會用掉了 ISN 這個起始序號, 可是在實作上, 真正開始傳送的 Payload 是從 ISN+1 開始編號。) 所有 A 送給 B 的封包, 都會標示所載送資料的第 1 Byte 的序號。
85
序號 (Sequence Number) 例如:ISN若設為 1000, 當 A 送出 Payload 長度分別為 100、200、300 Bytes 的 Packet1、2、3 給 B 時, 各個封包的序號值如下表所示:
86
序號 (Sequence Number)
87
回應序號 (Acknowledge Number)
回應序號代表期望自己下一次收到的封包序號。假設 X 給 Y 的回應序號為100, 代表 X 期望下一次收到 Y 傳來序號為 100 的封包;換一個角度來講, Y 傳給X 的下一個封包, 其序號應填入 100。不過, 回應序號還有另一種意義-用來確認之前的封包已經收到。也就是說, 既然 X 期望下一次收到序號為 100 的封包, 表示先前 Y 所傳送、序號小於 100 的封包, 都已經接收無誤了。
88
回應序號 (Acknowledge Number)
我們仍以表 為例, A 的 ISN 為 1000, 送出長度為 100 Bytes 的 Packet 1 給 B。B 回覆 ACK 1 時,ACK 1 的回應序號記錄著 1101, 代表 B 期望 A 下次送來的封包(亦即 Packet 2), 所載送資料的第 1 Byte 的編號是 1101。 下表列出 ACK 1、ACK 2、ACK 3 的回應序號:
89
回應序號 (Acknowledge Number)
90
回應序號 (Acknowledge Number)
簡言之, 初始序號 (ISN) 由 A (傳送端) 隨機產生, 而: Packet 1 的序號 = ISN+1 Packet 2 的序號 = ACK 1 的回應序號 Packet 3 的序號 = ACK 2 的回應序號 ...依此類推。 總結來說, 以上的觀念可以整理成為兩點:
91
回應序號 (Acknowledge Number)
從傳送端的角度來看:序號代表此封包的 TCP Payload 的第 1 個 Byte 從幾號開始編;回應序號代表對方回應 ACK 時, 該回應封包的序號。而且, 回應序號也代表在該序號之前的封包已經收到。 從接收端的角度來看:根據序號可知此封包的 TCP Payload 從哪個號碼開始;根據回應序號, 可知自己送出回應封包給對方時, 該回應封包的序號為何。
92
定義 Window 的邊界 Sliding Window 同樣是以 Byte 為單位來界定 Window, 而非以封包編號。
以Send Window 為例, 當 A 收到 ACK 1 封包後, Send Window 是以如下的方式來標示:
93
定義 Window 的邊界
94
定義 Window 的邊界 Receive Window 也是同樣的狀況。例如:B 收到 Packet 2 封包並回應 ACK2 後, Receive Window 是以如下的方式來標示:
95
定義 Window 的邊界
96
雙向傳輸 先前的模型都是以單向傳輸為例, 但是 TCP 是一個雙向的協定。換言之, 當A、B 之間建立好連線後, A 可以傳送資料給 B, 而 B 也可以傳送資料給 A。 讀者可以將 TCP 連線想像成由兩條單向管道所構成的雙向傳輸:
97
雙向傳輸
98
雙向傳輸 A→B 與 A←B 管道各有一組序號 / 回應序號與 Send / Receive Window, 因此整個 TCP 連線會有 2 個序號、2 個回應序號、2 個 Send Window, 以及 2 個Receive Window。
99
雙向傳輸 值得注意的是, A、B 之間互傳的封包, 其實可以是『一魚兩吃、雙重角色』。也就是說, 當 B 要回覆 ACK 封包給 A 時, 可以順便夾帶 B 要傳給 A 的資料一齊過去, 不必先傳 ACK 封包、再傳資料封包。因此在雙向傳輸過程中,幾乎每個封包都扮演『傳送兼回應、回應兼傳送』雙重角色。如右圖:
100
雙向傳輸
101
12-3-7 傳送機制小結 綜合上述由簡而繁的模型, 我們歸納出 TCP 幾項重要的傳送機制:
TCP 傳送包含流量控制的機制, 利用雙邊的 Sliding Window, 可視情況隨時調整資料傳送的速度。
102
傳送機制小結 TCP 將資料視為 Bytes Stream, 無論是資料的確認與重送, 或是 Sliding Window的邊界, 皆是在 Bytes Stream 上以 Byte 為單位來定義。 TCP 為雙向傳輸的協定, 同一個封包表頭內可包含雙向傳輸的資訊。 TCP 傳送的機制相當複雜, 讀者可能要花多一點時間去理解。不過如果能徹底理解這些機制, 將能輕易了解 TCP 運作的方式。
103
12-4 TCP 連線 所有 TCP 的傳輸都必須在 TCP 連線 (TCP Connection) 中進行。因此, TCP連線的建立、中止可說是 TCP 的基本工作。
104
識別連線 在介紹 TCP 連線前, 首先要說明如何定義一條 TCP 連線。TCP 連線是由連線兩端的 IP 位址與連接埠編號所定義:
105
識別連線 如果上圖的 B 是 Web 伺服器, 雖然 B 使用同樣的 IP 位址和同樣的連接埠編號, 但可以和同一用戶端的不同連接埠建立多條連線, 或是和不同的用戶端同時建立連線。
106
識別連線
107
建立連線 開始建立連線時, 一定會有一方為主動端 (Active), 另一方為被動端 (Passive)。以 WWW 為例, 用戶端的瀏覽器通常扮演主動端的角色, 而伺服器的 Web 服務通常是被動端的角色。 連線建立之初, 主要是讓雙方知道對方使用的各項 TCP 參數。亦即, 在建立連線時, 必須交換以下資訊: 雙方的 ISN (初始序號)。 雙方的 Window Size。
108
建立連線 整個連線建立的過程稱為『Handshaking』, 也就是雙方一見面時要先握手打招呼, 講好如何建立連線。Handshaking 總共有 3 個步驟, 每個步驟各有一個 TCP封包。接著我們便以 A 為 TCP 主動端, B 為被動端為例, 說明 Handshaking 的過程。由於整個過程會涉及 A、B 雙向管道的建立, 因此我們仍以 A→B、A←B 的表示法來代表兩種方向的傳輸管道。
109
第 1 步驟 A 首先送出第 1 個 TCP 封包給 B, 我們稱它為 SYN (Synchronize, 同步) 封包。此封包除了指明 A、B 雙方的連接埠編號外, 還必須包含以下資訊: 序號:指定 A→B 的 ISN, 我們稱之為 ISN(A→B)。序號長度為 4 Bytes, 由電腦隨機產生。
110
第 1 步驟 回應序號:指定 A←B 的回應序號。因為現在還不知道 A←B 的初始序號為何, 因此回應序號先設為 0。
SYN Flag:這是 TCP 表頭中的一個標示位元, 用來表明此封包的序號為 ISN,而非一般的序號。 Window Size:A 預設 Receive Window 的大小, 在此我們稱之為 Window(A←B)。它可用來控制 B 的 Send Window 大小, 藉此達成 A←B 的流量控制。
111
第 2 步驟 B 在收到 SYN 封包後, 接著會回覆一個 SYN-ACK 封包, 其中包含了以下資訊:
序號:指定 A←B 的 ISN, 我們稱之為 ISN(A←B)。 回應序號:從 SYN 封包已經得知 ISN( A→B), 因此 SYN-ACK 封包的回應序號等於 ISN(A→B) 再加上 1, 表示期望 A 下一次送來的 TCP 資料是以 ISN(A→B)+1為第 1 個 Byte 的編號。
112
第 2 步驟 SYN-ACK Flag:SYN-ACK 的 SYN 同樣是 Synchronize 的意思, ACK 則是Acknowledgement, 用來表明此封包的序號為 ISN (A←B), 同時表示回應序號包含了確認收到的資訊。 Window Size:B 預設 Receive Window 的大小, 稱為 Window(A→B)。它可用來控制 A 的 Send Window 大小, 藉此達成 A→B 的流量控制。
113
第 3 步驟 A 在收到 SYN-ACK 封包後, 接著會再發出一個 ACK 封包, 其中包含了以下資訊:
序號:A→B 的資料的第 1 個 Byte編號, 也就是 SYN-ACK封包的回應序號。 回應序號:從第 2 步驟的 SYN-ACK 封包可得知 A←B 的 ISN。同理, 在 A←B 傳輸管道中, A 也尚未收到任何資料, 所以此處的序號等於 ISN(A←B) 再加上 1, 表示 A 期望 B 下次送來的資料, 是以 ISN(A←B)+1為第 1 Byte 的編號。
114
第 3 步驟 ACK Flag:表示回應序號包含了確認收到的資訊。
Window Size:A 的 Receive Window 大小, 亦即 Window(A←B)。 建立連線的 3 個步驟可總結成如下的示意圖:
115
第 3 步驟
116
中止連線 TCP 連線若要中止, 必須經由特定的連線中止步驟, 才能將連線所用的資源(連接埠、記憶體等等) 釋放出來。請讀者注意, 雖然建立連線時可區分為主動端與被動端, 但是雙方都可以主動提出中止連線的要求。 連線中止的過程共有 4 個步驟, 每個步驟各有一個 TCP 封包。接著我們便以A 主動提出連線中止為例, 說明連線中止的過程。
117
第 1 步驟 A 首先送出第 1 個 TCP 封包給 B, 我們稱它為 FIN-ACK (FIN 是 Finish 的縮寫) 封包, 其中包含了以下資訊: 序號:指定 A→B 的序號, 因為 A→B 的傳輸即將中止, 故此序號又稱為 FSN(Final Sequence Number, 最終序號), 我們以 FSN(A→B) 來表示。 回應序號:指定 A←B 的回應序號。
118
第 1 步驟 FIN-ACK Flag:意思是說 A→B 已經傳輸完畢, ACK 表示回應序號包含了確認收到的資訊。
Window Size:與一般相同, 以下省略。
119
第 2 步驟 B 送出 ACK 封包給 A, 其中包含了以下資訊: 序號:指定 A←B 的序號。
回應序號:指定 A→B 的回應序號, 此處回應序號等於第 1 步驟 FIN-ACK 封包的 FSN(A→B) 再加上 1。 ACK Flag:表示回應序號包含了確認收到的資訊。
120
第 2 步驟 此步驟結束後, 代表成功地中止 A→B 傳輸管道。不過, A←B 可能還有資料需要傳送, 所以 A←B 傳輸管道仍舊繼續維持暢通, 直到傳送完畢才會進入第 3步驟。
121
第 3 步驟 當 B 完成 A←B 的傳輸後, 便送出 FIN-ACK 封包給 A, 其中包含了以下資訊:
序號:指定 A←B 的序號, 因為已完成傳輸, 因此稱之為 FSN(A←B)。 回應序號:指定 A→B 的回應序號。由於第 1 步驟結束後, A 便不再傳送資料給 B, 所以此處的回應序號與第 2 步驟的回應序號相同, 皆為 FSN(A→B) + 1。 FIN-ACK Flag:代表 A←B 已經傳輸完畢, 且回應序號包含了確認收到的資訊。
122
第 4 步驟 A 送出 ACK 封包給 B, 其中包含了以下資訊:
序號:指定 A →B 的序號, 此處序號等於第 1 步驟 FIN-ACK 封包的 FSN(A→B) 再加上 1。 回應序號:指定 A←B 的回應序號, 此處回應序號等於第 3 步驟 FIN-ACK 封包的 FSN(A←B) 再加上 1。 ACK Flag:表示回應序號包含了確認收到的資訊。
123
第 4 步驟 中止連線的 4 個步驟可總結成如右的示意圖:
124
12-5 TCP 封包 TCP 封包是由以下兩部份所組成:
TCP 表頭:記錄來源端與目的端應用程式所用的連接埠編號, 以及相關的 Sequence Number 、回應序號、Window Size 等等。
125
TCP 封包 TCP 資料:載送上層協定 (例如:Application Layer) 的資訊。這部份可視為 TCP Payload, 不過一般都稱為 TCP Segment, 本章我們將稱之為『TCP 資料』。 TCP 表頭記錄了 TCP 連線的重要資訊, 包含的欄位如下:
126
TCP 封包
127
TCP 封包 接下來我們便摘要說明 TCP 表頭的欄位。由於同一個 TCP 封包表頭內有些欄位記錄了送出管道的資訊, 有些欄位則是接收管道的資訊, 因此我們仍舊以 A、B 為例, 解釋 A 所發出 TCP 封包的表頭欄位。
128
來源與目的連接埠編號 來源連接埠編號:記錄 A 上層應用程式所用的 TCP 連接埠編號。
目的連接埠編號:記錄 B 上層應用程式所用的 TCP 連接埠編號。
129
序號與回應序號 序號:記錄此封包所含的 TCP 資料的第 1 Byte 的編號。
回應序號:記錄下次 B 傳送資料給 A 時, 第 1 Byte 資料所使用的編號。
130
資料長度 長度為 4 Bits, 記錄 TCP 表頭的長度, 以 4 Bytes 為計量單位。例如:此欄位紀錄的值若是 5, 代表 TCP 表頭的長度為 20 Bytes (5× 4 = 20)。 在 TCP 表頭中, 除了 Options 與 Padding 欄位非固定長度外, 其他的欄位都是固定長度。換言之, TCP 表頭長度主要是隨著 Options 與 Padding 這兩個欄位的長度而有所變化。
131
資料長度 Options 與 Padding 的欄位長度最短是 0, 也就是沒有這兩個欄位, 此時 TCP 表頭的長度為 20 Bytes。後文會再說明 Options 與 Padding 欄位。
132
標示位元 標示位元 (Flag) 可用來通知對方表頭中記錄了哪些有用的資訊。以下為 TCP表頭中常用的標示位元。
Acknowledge (回應) 代表回應序號欄位包含了確認的資訊。 Synchronize (同步) 代表序號欄位記載的是 ISN, 換言之, 此封包為連線建立時第 1 或第 2 步驟的封包。
133
標示位元 Urgent (緊急) 在介紹 Receive Window 時, 我們曾經說明 (以 A→B 為例) B 只會針對完整收到的部份發出 ACK 封包, 同樣地也只會將完整收到的部份轉交給上層應用程式。 在實際應用上, A 應用程式可能要傳送一些必須即時處理的資訊, 例如:控制資訊。換言之, 負責傳送這些緊急資訊的封包, 最好不必排隊, 而能夠立即 『插隊』。
134
標示位元 Urgent Flag 設為 1 時, 代表 B 必須立即處理此封包的資料。
Urgent 封包除了載送 Urgent 的資料外, 也可能包含一般的資料。因此, 必須在 TCP 資料中定義哪部份屬於 Urgent 資料。此項資訊記錄在隨後的緊急資料指標欄位中。
135
標示位元 Finish (完成) 代表 A→B 已傳送完畢。只有在 節中止連線的第 1 或第 3 步驟, 才會設定此標示位元。
136
Window Size 用來告訴 B:『 A 的 Receive Window 有多大』 , 以控制 A←B 的流量。一般而言, 若 A 有充裕的時間處理 A←B 傳送來的資料時, A 的 Receive Window 可變大;若 A 過於忙碌而無暇處理 A←B 傳送來的資料時, A 的 Receive Window會變小。
137
檢查碼 長度為 2 Bytes, 記錄錯誤檢查碼。TCP 在計算錯誤檢查碼時, 會加上 TCPPseudo Header。其運作方式與 UDP 的錯誤檢查碼完全相同, 在此不再贅述。
138
Urgent Pointer (緊急資料指標)
長度為 2 Bytes。當 Urgent Flag 設為 1 時, 本欄位記錄 TCP 資料中, 屬於Urgent 資料的最後一個 Byte。例如:緊急資料指標欄位值為 3 時, 代表 TCP 資料的前 4 Bytes (從第 0 到第 3 個 Byte) 為 Urgent 資料。
139
Options and Padding Options 欄位長度不定, 可用來擴充 TCP 的功能, 以下我們將介紹 MSS、SACK-Permitted 和 SACK 這 3 種常見的擴充功能;Padding 欄位則是為了讓TCP 表頭 (包含 Options 欄位) 剛好是 4 Bytes 的倍數。
140
Options and Padding Options 欄位的格式如下:
Option Kind:長度為 1 Byte, 以代號表示 Options 欄位的用途, 例如:2代表MSS、4 代表 SACK-Permitted、5 代表 SACK。 Option Length:長度為 1 Byte, 記錄 Option 欄位的總長度, 單位為 Byte。 Option Data:長度不定, 記錄 Option 的資料。Option Data 的長度等於 Option Length 欄位值減 2 (Option Kind 與 Option Length 各佔用 1 Byte)。
141
MSS MSS 為 Maximum Segment Size 的縮寫。此選項主要是在建立連線 (SYN Flag=1) 時, 用來指定所能傳送 TCP 資料最大的長度。以 A、B 為例, 在連線建立的第 1 步驟, A 將其 MSS 值送給 B, B 則是在第 2 步驟將其 MSS 值送給 A。兩者之間取最小值, 在該連線過程中, 無論是 A→B 或 A←B 管道的 TCP 資料長度都不會大於該值。
142
MSS 一般情況下, TCP 封包會小於或等於 IP Payload 的長度, 以免還要將 TCP 封包切割後才能裝入 IP Payload。因此之故, MSS 的預設值為 MTU 減去 IP 表頭的最小長度, 再減去 TCP 表頭的最小長度。以乙太網路為例, MTU 為 1500 Bytes,減去 IP 表頭的最小長度 (20 Bytes), 再減去 TCP 表頭的最小長度 (20 Bytes), 則MSS 預設值為 1460。
143
MSS MSS 選項的各個欄位值如下: Option Kind:MSS 的代號為 2。
Option Length:MSS 選項的總長度為 4 Bytes, 所以這個欄位值為 4。 Option Data:長度為 2 Bytes, 記錄 MSS 值, 單位為 Byte。
144
SACK-Permitted 在 A→B 傳輸管道中, B 只會針對連續收到的封包發出 ACK 訊息。以下圖為例, 假設 A 送 4 筆長度皆為 100 Bytes 的封包給 B, 由於 B 始終未收到序號 的資料, 雖然後續的資料 (200~299 與 300~399) 都到齊了, 也不會傳送 ACK封包給 A。因此, 當 A 收不到 ACK 而須重送時, 勢必重送序號 的資料, 造成序號 的資料重複發送的情形。
145
SACK-Permitted
146
SACK-Permitted 為了避免上述情況發生, TCP 可使用 SACK (Selective Acknowledgement)和 SACK-Permitted 功能。SACK-Permitted 是在連線建立時, 雙方互相溝通是否要使用 SACK 功能;SACK 功能則是連線建立後的傳送過程中, 用來告知對方不必重送哪些封包。以上例而言, B 可以利用 SACK , 告知 A 已收到序號 這些沒有連續收到的封包, 因此 A 便不用重送這部份資料。
147
SACK-Permitted SACK-Permitted 只會用在 SYN Flag 為 1 的封包, 也就是連線建立過程中的第 1 或第 2 步驟。以 A、B 為例, 若 A 在第 1 步驟中使用了 SACK-Permitted , 代表 A 具有 SACK 的能力, 亦即 B 在連線過程中, 可以傳送具有 SACK 功能的 ACK封包給 A。
148
SACK-Permitted 具有 SACK-Permitted 功能的 Options 欄位值如下:
Option Kind:SACK-Permitted 選項的代號為 4。 Option Length:SACK-Permitted 選項的總長度為 2 Bytes, 故此欄位值為 2。 Option Data:長度為 0。
149
SACK 只有當 ACK Flag 設為 1 時, 才會使用 SACK 功能。以 A→B 為例, 當 B 在傳送 ACK 封包給 A 時, 可利用 SACK 告知不必重送哪些封包。若要告知的內容分為多段, 則可在 Option Data 欄位中, 定義每段資料的起始與結束序號。 其各個欄位值如下:
150
SACK Option Kind:SACK 選項的代號為 5。
Option Length:SACK 選項的總長度不定。每定義一段非連續性資料需要 8Bytes (起始序號與結束序號各 4 Bytes)。 第 1 段沒有連續收到的資料的起始序號, 長度為 4 Bytes。
151
SACK 第 1 段沒有連續收到的資料的結束序號, 長度為 4 Bytes。
152
12-6 擷取 TCP 封包 接下來我們利用 NetAnalyzer 擷取 TCP 連線建立時的封包, 以及傳送資料的封包, 實際檢視封包的內容。
153
環境設定 我們使用如右兩部電腦來擷取封包:
154
環境設定 開始擷取封包後, 我們從 Brower 連線到 Web Server, 擷取一開始建立 TCP 連線的封包。
155
建立連線 以下將逐一檢視 TCP 連線建立時, 各個步驟的封包。 第 1 步驟 第 2 步驟 第 3 步驟
156
第 1 步驟
157
第 1 步驟 Browser 所用的連接埠, 屬於 Registered / Dynamic 的連接埠。
Web Server 所用的連接埠, 一般使用編號為 80 的連接埠。 這是由 Browser 端系統隨機選取的起始序號(Initial Sequence Number),為了方便說明, 我們稱之為 ISN(Browser→Server)。 TCP 表頭的長度。表頭中固定長度的欄位佔了 20 Bytes, 另外又加上8 Bytes 的選項。
158
第 1 步驟 標示位元欄位, 只有 SYN Flag 設為 1。 Browser 預設的 Receive Window 大小。 錯誤檢查碼。
MSS 選項, 因為是在乙太網路上, 因此 MSS 值為 1460 Bytes。 SACK-Permitted 選項, 表示 Browser 端可接受帶有 SACK 選項的 ACK 封包。
159
第 2 步驟
160
第 2 步驟 Web Server 所用的連接埠。 Browser 所用的連接埠。
這是由 Web Server 端系統隨機選取的起始序號(Initial Sequence Number), 為了方便說明, 我們稱之為 ISN(Browser←Server)。 ISN(Browser→Server) + 1。 TCP 表頭的長度。表頭中固定長度的欄位佔了 20 Bytes, 另外又加上 8 Bytes的選項。
161
第 2 步驟 標示位元欄位, ACK 與 SYN Flag 皆設為 1。 Web Server 預設的 Receive Window 大小。
錯誤檢查碼。 MSS 選項, 因為是在乙太網路上, 因此 MSS 值為 1460 Bytes。 SACK-Permitted 選項, 表示 Web Server 端可接受帶有 SACK 選項的 ACK 封包。
162
第 3 步驟
163
第 3 步驟 ISN(Browser→Server) + 1。 ISN(Browser←Server) + 1。
TCP 表頭的長度。由於未使用任何選項, 因此長度為 20 Bytes。 標示位元欄位, 只有 ACK Flag 設為 1。 Browser 的 Receive Window 大小。
Similar presentations