通訊網路/TCP 和 UDP 協議/TCP
在瞭解了模型的各個層次之後,現在該看看 TCP 協議並研究其功能了。本節將幫助讀者瞭解 TCP 的概念和特性,然後逐步深入瞭解 TCP 的細節,如連線建立/關閉、TCP 中的通訊,以及為什麼 TCP 協議被稱為可靠協議和自適應協議。本節將以 UDP 和 TCP 的比較結束,並附帶一個很好的練習,鼓勵讀者解決更多問題。
在編寫本節之前,資訊已從各種來源學習,如 TCP 指南、RFC、Tanenbaum 的書和課堂筆記。
什麼是 TCP?
從理論上講,傳輸層協議可以是一個非常簡單的軟體例程,但 TCP 協議不能稱為簡單。為什麼要使用像 TCP 那樣複雜的傳輸層?最重要的原因取決於 IP 的不可靠性。事實上,TCP 下面的所有層都是不可靠的,並且逐跳傳遞資料報。IP 層逐跳傳遞資料報,不保證資料報的傳遞;它是一個無連線系統。IP 只是處理資料報的路由;如果出現問題,IP 會毫不猶豫地丟棄資料包,並在此過程中向傳送方傳送錯誤訊息。確定透過網路傳送的資料報狀態和處理如果部分資料報被丟棄則重新發送資訊的任務由 TCP 完成。
大多數使用者將 TCP 和 IP 視為緊密結合的一對,但 TCP 可以並且經常與其他傳輸協議一起使用。
例如,TCP 或其部分內容用於檔案傳輸協議 (FTP) 和簡單郵件傳輸協議 (SMTP),它們都不使用 IP。
傳輸控制協議為 IP 層和上層提供了相當多的服務。最重要的是,它為上層提供了一個面向連線的協議,使應用程式能夠確定透過網路傳送的資料報是否完整地接收。在這種情況下,TCP 充當訊息驗證協議,提供可靠的通訊。如果資料報損壞或丟失,通常是 TCP(而不是更高層的應用程式)處理重傳。
TCP 不是軟體。它是一種通訊協議。
TCP 管理來自更高層的以及來自 IP 層的傳入資料報的流。它必須確保優先順序和安全性得到尊重。TCP 必須能夠處理在其上層正在等待傳入資料報的應用程式的終止,以及較低層中的故障。TCP 還必須維護一個所有進出 TCP 層的資料流狀態表。將這些服務隔離在單獨的層中,使應用程式的設計無需考慮流控制或訊息可靠性。如果沒有 TCP 層,每個應用程式都必須自己實現這些服務,這是一種浪費資源。
TCP 位於傳輸層,位於 IP 之上,但在上層及其應用程式之下,如下圖所示。TCP 只駐留在實際處理資料報的裝置上,以確保資料報已從源機器傳遞到目標機器。它不駐留在只路由資料報的裝置上,因此閘道器中沒有 TCP 層。這是有道理的,因為在閘道器上,資料報不需要在分層模型中比 IP 層更高。
圖 1:TCP 提供可靠的端到端通訊
由於 TCP 是一種面向連線的協議,負責確保資料報從源機器傳遞到目標機器(端到端通訊),因此 TCP 必須接收來自目標機器的通訊訊息以確認資料報的接收。術語虛擬電路通常用於指代兩臺終端機器之間進行的握手,其中大多數是簡單的確認訊息(接收確認或故障程式碼)和資料報序列號。它類似於電話通話;有人透過撥打電話號碼來發起通話,該號碼被接聽,進行雙向通話,最後有人結束通話。套接字對標識連線的兩端,即虛擬電路。可能需要提醒的是,套接字由 IP 地址和埠號組成,以標識位置。伺服器使用眾所周知的埠號(< 1000)來表示標準化服務(偵聽)。超過 1024 的數字可供使用者自由使用。下表列出了某些標準服務的埠號。
| 埠 | 協議 | 用途 |
|---|---|---|
| 21 | FTP | 檔案傳輸 |
| 23 | Telnet | 遠端登入 |
| 25 | SMTP | 電子郵件 |
| 69 | TFTP | 微不足道的檔案傳輸協議 |
| 79 | Finger | 查詢有關使用者的詳細資訊 |
| 80 | HTTP | 全球資訊網 |
| 110 | POP-3 | 遠端電子郵件訪問 |
| 119 | NNTP | USENET 新聞 |
位元組流或訊息流?
嗯,訊息邊界在 TCP 中沒有端到端保留。例如,如果傳送程序對 TCP 流進行四個 512 位元組的寫入操作,這些資料可能會作為四個 512 位元組的塊、兩個 1024 位元組的塊、一個 2048 位元組的塊或其他方式傳遞給接收程序。接收方無法檢測到寫入資料的單元。TCP 實體接受來自本地程序的使用者資料流,將其分成不超過 64 KB 的片段(實際上,通常為 1460 個數據位元組,以便與 IP 和 TCP 首部一起放入單個乙太網幀),並將每個片段作為單獨的 IP 資料報傳送。當包含 TCP 資料的資料報到達機器時,它們會被傳遞給 TCP 實體,後者會重建原始位元組流。為簡單起見,我們有時會使用TCP來指代 TCP 傳輸實體(一塊軟體)或 TCP 協議(一組規則)。從上下文中可以清楚地知道指的是哪一個。例如,在使用者向 TCP 提供資料中,顯然指的是 TCP 傳輸實體。IP 層不保證資料報會正確傳遞,因此 TCP 必須在需要時超時並重新傳輸它們。到達的資料報很可能以錯誤的順序到達;TCP 也必須將它們重新組裝成按正確順序排列的訊息。簡而言之,TCP 必須提供大多數使用者想要而 IP 未提供的可靠性。
TCP 的特點
TCP 在每個主機系統上的程序之間提供通訊通道。該通道是可靠的、全雙工的和流式的。為了實現此功能,TCP 驅動程式將會話資料流分解成離散的段,併為每個段附加一個 TCP 首部。將一個 IP 首部附加到這個 TCP 資料包,然後將複合資料包傳遞給網路以進行傳遞。此 TCP 首部具有用於支援預期的 TCP 功能的眾多欄位。TCP 具有以下功能特性
單播協議 : TCP 基於單播網路模型,支援兩個精確的雙方之間的資料交換。它不支援廣播或組播網路模型。
連線狀態 : 而不是在網路內施加狀態來支援連線,TCP 在兩個端點之間使用同步狀態。這種同步狀態是在初始連線過程的一部分中建立的,因此 TCP 可以被視為一個面向連線的協議。協議設計的大部分內容旨在確保每個本地狀態轉換都被傳達給遠端方並得到遠端方的確認。
可靠的 : 可靠性意味著傳遞到連線一端的 TCP 驅動程式的八位位元組流將被傳輸到整個網路,以便將該流作為與傳送方生成的相同順序的相同八位位元組序列呈現給遠端程序。這意味著協議檢測到資料流的段何時被網路丟棄、重新排序、重複或損壞。如果需要,傳送方將重新傳輸損壞的段,以便接收方能夠重建原始資料流。這意味著 TCP 傳送方必須保留所有已傳輸資料的本地副本,直到收到指示接收方已完成資料準確傳輸的指示。
全雙工 : TCP 是一種全雙工協議;它允許雙方在單個 TCP 連線的上下文中傳送和接收資料。
流式 : 儘管 TCP 使用資料包結構進行網路傳輸,但 TCP 是一種真正的流式協議,應用程式級別的網路操作不是透明的。某些協議明確封裝每個應用程式事務;對於每次寫入,都必須有一個匹配的讀取操作。透過這種方式,應用程式派生的資料流邏輯記錄結構的分割在網路上被保留。TCP 不保留施加在資料流上的這種隱式結構,因此網路協議中沒有寫入和讀取操作之間的配對。例如,TCP 應用程式可以將三個資料塊依次寫入網路連線,這些資料塊可以被遠端讀取器在一個讀取操作中收集。在會話開始時協商 TCP 會話中使用的資料塊(段)的大小。傳送方嘗試在其接收方最大段大小、配置的傳送方最大段大小以及網路路徑最大可支援的非分段資料包大小(路徑最大傳輸單元 [MTU])的限制內,使用它可以使用的最大段大小進行資料傳輸。路徑 MTU 會定期重新整理,以適應 TCP 連線處於活動狀態時網路中可能發生的任何更改。
速率自適應: TCP 也是一種速率自適應協議,資料傳輸速率旨在適應網路中普遍存在的負載條件,並適應接收端的處理能力。沒有預定的 TCP 資料傳輸速率;如果網路和接收器都具有額外的可用容量,則 TCP 傳送方將嘗試將更多資料注入網路以佔用此可用空間。相反,如果出現擁塞,TCP 傳送方將降低其傳送速率以允許網路恢復。此自適應功能試圖在不觸發一致資料丟失的情況下實現儘可能高的資料傳輸速率。
TCP 段以網際網路資料報的形式傳送。網際網路協議報頭包含幾個資訊欄位,包括源主機地址和目標主機地址。TCP 報頭位於網際網路報頭之後,提供特定於 TCP 協議的資訊。這種劃分允許存在除 TCP 之外的主機級協議。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |U|A|P|R|S|F| |
| Offset| Reserved |R|C|S|S|Y|I| Window |
| | |G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP Header Format
Note that one tick mark represents one bit position.
源埠:16 位 源埠號。
目標埠:16 位 目標埠號。
序列號:32 位 此段中第一個資料位元組的序列號(除非存在 SYN)。如果存在 SYN,則序列號是初始序列號 (ISN),第一個資料位元組是 ISN+1。
確認號:32 位 如果設定了 ACK 控制位,則此欄位包含段傳送方期望接收的下一個序列號的值。一旦建立連線,這將始終被髮送。
資料偏移量:4 位 TCP 首部中的 32 位字數。這指示資料開始的位置。TCP 首部(即使包含選項)也是 32 位整數倍。
保留:6 位 為將來使用保留。必須為零。
控制位:6 位(從左到右)
URG:緊急指標欄位有效
ACK:確認欄位有效
PSH:推送功能
RST:重置連線
SYN:同步序列號
FIN:傳送方不再有資料
視窗:16 位 從確認欄位中指示的第一個資料位元組開始,該段傳送方願意接受的資料位元組數。
校驗和:16 位 校驗和欄位是首部和文字中所有 16 位字的按位取反和的 16 位按位取反。如果一個段包含奇數個要進行校驗和計算的首部和文字位元組,則最後一個位元組在右側填充零以形成一個 16 位字以進行校驗和計算。填充不會作為段的一部分傳輸。在計算校驗和時,校驗和欄位本身被替換為零。
校驗和還覆蓋概念上加在 TCP 首部之前的 96 位偽首部。此偽首部包含源地址、目標地址、協議和 TCP 長度。這為 TCP 提供了針對錯誤路由段的保護。此資訊包含在網際網路協議中,並在 TCP/網路介面中透過 TCP 對 IP 的呼叫引數或結果進行傳輸。
TCP 長度是 TCP 首部長度加上資料長度(以位元組為單位)(這不是顯式傳輸的數量,而是計算出來的),並且不包括偽首部的 12 個位元組。
緊急指標:16 位 此欄位以從此段中的序列號開始的正偏移量形式傳達緊急指標的當前值。緊急指標指向緊急資料後一個位元組的序列號。此欄位僅在設定了 URG 控制位的段中進行解釋。
選項:可變 選項可以佔用 TCP 首部末尾的空間,並且長度為 8 位的倍數。所有選項都包含在校驗和中。選項可以從任何位元組邊界開始。選項格式有兩種情況
情況 1:一個位元組的選項型別。
情況 2:一個位元組的選項型別、一個位元組的選項長度和實際的選項資料位元組。選項長度包括選項型別和選項長度這兩個位元組,以及選項資料位元組。請注意,選項列表可能比資料偏移量欄位所暗示的要短。選項結束選項之外的標頭內容必須是標頭填充(即零)。
TCP 必須實現所有選項
Ethereal 捕獲
可以使用 Ethereal 捕獲檢視 TCP 資料包。下面捕獲並顯示了一個這樣的 TCP 資料包。請注意,其中設定了 ACK 標誌和 PUSH 標誌,值為“1”。
在 TCP 可以用於任何實際有用的目的(即傳送資料)之前,必須在希望進行通訊的兩個裝置之間建立連線。此過程通常稱為連線建立,它涉及交換訊息,使兩個裝置從其初始連線狀態(關閉)轉換到正常工作狀態(已建立)。
連線建立功能
連線建立過程實際上在建立適合資料交換的連線時完成了幾個事情
聯絡和通訊: 客戶端和伺服器透過相互發送訊息來進行聯絡並建立通訊。在此之前,伺服器通常甚至不知道它將與哪個客戶端進行通訊,因此它在連線建立過程中發現了這一點。
序列號同步: 每個裝置都讓對方知道它希望將其第一次傳輸用於哪個初始序列號。
引數交換: 兩個裝置交換控制 TCP 連線操作的某些引數。
用於連線建立的控制訊息:SYN 和 ACK
TCP 使用控制訊息來管理聯絡和通訊的過程。但是,沒有特殊的 TCP 控制訊息型別;所有 TCP 訊息都使用相同的段格式。TCP 首部中的一組控制標誌指示段是用於控制目的還是僅用於攜帶資料。使用控制訊息時,以下標誌會發生改變。
SYN: 此位表示段用於初始化連線。SYN 代表同步,指的是我上面提到的序列號同步。
ACK: 此位表示傳送段的裝置正在傳遞對收到的訊息(例如 SYN)的確認。
正常連線建立:“三次握手”
為了建立連線,每個裝置都必須傳送一個 SYN 並接收來自對方裝置的 ACK。因此,從概念上講,需要在裝置之間傳遞四個控制訊息。但是,當一個人可以同時傳遞兩者時,分別傳送一個 SYN 和一個 ACK 是低效的。因此,在連線建立的正常事件序列中,一個 SYN 和一個 ACK 透過設定相關位的兩個標誌同時傳送(有時稱為 SYN+ACK 訊息)。這總共需要三個訊息,因此該連線過程被稱為三次握手。
Key Concept: The normal process of establishing a connection between a TCP client and server involves three steps:
客戶端傳送一個 SYN 訊息;伺服器傳送一個訊息,該訊息包含對客戶端 SYN 的 ACK,幷包含伺服器的 SYN;然後客戶端傳送對伺服器 SYN 的 ACK。這被稱為 TCP 三次握手。
連線在其生命週期內會經過一系列狀態。
狀態包括:監聽、SYN 已傳送、SYN 已接收、已建立、FIN-WAIT-1、FIN-WAIT-2、CLOSE-WAIT、CLOSING、LAST-ACK、TIME-WAIT 和虛構狀態關閉。關閉是虛構的,因為它表示沒有 TCB,因此沒有連線。簡而言之,這些狀態的含義是
監聽 - 表示正在等待來自任何遠端 TCP 和埠的連線請求。
SYN 已傳送 - 表示在傳送連線請求後正在等待匹配的連線請求。
SYN 已接收 - 表示在收到和傳送連線請求後正在等待確認連線請求確認。
已建立 - 表示連線已開啟,收到的資料可以傳遞給使用者。連線資料傳輸階段的正常狀態。
FIN-WAIT-1 - 表示正在等待來自遠端 TCP 的連線終止請求,或者正在等待對之前傳送的連線終止請求的確認。
FIN-WAIT-2 - 表示正在等待來自遠端 TCP 的連線終止請求。
CLOSE-WAIT - 表示正在等待來自本地使用者的連線終止請求。
CLOSING - 表示正在等待來自遠端 TCP 的連線終止請求確認。
LAST-ACK - 表示正在等待對之前傳送給遠端 TCP 的連線終止請求的確認(其中包括對連線終止請求的確認)。
TIME-WAIT - 表示正在等待足夠的時間過去以確保遠端 TCP 收到了對其連線終止請求的確認。
關閉 - 表示根本沒有連線狀態。
TCP 連線會響應事件從一種狀態轉換為另一種狀態。事件是使用者呼叫、開啟、傳送、接收、關閉、中止和狀態;傳入段,特別是包含 SYN、ACK、RST 和 FIN 標誌的段;以及超時。
圖 6 中的狀態圖僅說明狀態變化,以及導致的事件和產生的操作,但沒有涉及錯誤條件或與狀態變化無關的操作。在後面的部分中,將提供有關 TCP 對事件的反應的更多詳細資訊。
Key Concept: If one device setting up a TCP connection sends a SYN and then receives a SYN from the other one before its SYN is acknowledged, the two devices perform a simultaneous open, which consists of the exchange of two independent SYN and ACK message sets. The end result is the same as the conventional three-way handshake, but the process of getting to the ESTABLISHED state is different. The possibility of collision normally occurs in Peer-2-Peer connection.
緩衝區管理 當傳送方(在本例中假設為客戶端)要建立連線時,資料包會進入傳輸緩衝區。資料包應附加一些序列號。傳送方選擇序列號以最大程度地降低使用已使用序列號的風險。客戶端使用該序列號和資料以及資料包長度欄位傳送資料包。伺服器在接收到資料包後,會發送下一個預期序列號的確認(ACK)。它還會發送帶有自身序列號的 SYN。
客戶端在接收到這兩個訊息(SYN 和 ACK)後,會向接收方傳送 ACK,其中包含從接收方獲取的下一個預期序列號。因此,在客戶端和伺服器之間建立了序列號。現在,它們已準備好進行資料傳輸。即使在傳送資料時,也遵循相同的序列號概念。
TCP 傳輸策略
TCP 中的視窗管理不像大多數資料鏈路協議那樣直接與確認相關聯。例如,假設接收方具有 4096 位元組的緩衝區,如圖所示。如果傳送方傳輸了一個 2048 位元組的段,並且該段被正確接收,接收方將確認該段。但是,由於它現在只有 2048 位元組的緩衝區空間(直到應用程式從緩衝區中刪除一些資料),它將以下一個預期位元組開始,通告一個大小為 2048 的視窗。
現在傳送方傳輸了另外 2048 位元組,這些位元組被確認,但通告的視窗為 0。傳送方必須停止,直到接收主機上的應用程式程序從緩衝區中刪除一些資料,此時 TCP 可以通告一個更大的視窗。
當視窗為 0 時,傳送方通常可能不會發送段,但有兩種例外情況。首先,可以傳送緊急資料,例如,允許使用者終止在遠端機器上執行的程序。其次,傳送方可以傳送一個 1 位元組的段,使接收方重新通告下一個預期位元組和視窗大小。TCP 標準明確提供此選項以防止在視窗通告丟失時發生死鎖。
傳送方不需要在應用程式中的資料到達後立即傳輸資料。接收方也不需要儘快傳送確認。當前 2 KB 的資料到達時,TCP 知道有一個 4 KB 的視窗可用,完全可以將資料緩衝起來,直到另外 2 KB 的資料到達,以便能夠傳輸一個有效負載為 4 KB 的段。這種靈活性可以用來提高效能。
考慮一個與互動式編輯器建立的 telnet 連線,該編輯器會對每個按鍵做出反應。在最壞的情況下,當一個字元到達傳送 TCP 實體時,TCP 會建立一個 21 位元組的 TCP 段,然後將其交給 IP 作為 41 位元組的 IP 資料報傳送。在接收方,TCP 會立即傳送一個 40 位元組的確認(20 位元組的 TCP 頭部和 20 位元組的 IP 頭部)。稍後,當編輯器讀取了該位元組時,TCP 會發送一個視窗更新,將視窗向右移動 1 個位元組。此資料包也是 40 位元組。最後,當編輯器處理完該字元後,它會以 41 位元組資料包的形式回顯該字元。總共使用了 162 位元組的頻寬,併為每個輸入的字元傳送了四個段。當頻寬稀缺時,這種處理方式不可取。
許多 TCP 實現用來最佳化這種情況的一種方法是將確認和視窗更新延遲 500 毫秒,以期獲得一些可以免費搭乘的資料。假設編輯器在 500 毫秒內回顯,現在只需要將一個 41 位元組資料包傳送回遠端使用者,從而將資料包數量和頻寬使用量減少一半。雖然此規則減少了接收方對網路的負載,但傳送方仍然透過傳送包含 1 位元組資料的 41 位元組資料包的方式低效地執行。減少這種使用的一種方法稱為 Nagle 演算法(Nagle,1984)。Nagle 建議很簡單:當資料一次一個位元組地進入傳送方時,只發送第一個位元組,並將所有其他位元組緩衝起來,直到確認了未完成的位元組。然後,將所有緩衝的字元在一個 TCP 段中傳送,並開始重新緩衝,直到它們全部被確認。如果使用者打字速度很快,並且網路速度很慢,每個段中可能會包含大量的字元,從而大大減少了頻寬的使用。該演算法還允許在足夠的資料累積到足以填滿視窗的一半或最大段時傳送新資料包。
Nagle 演算法被 TCP 實現廣泛使用,但在某些情況下,最好停用它。特別是,當透過網際網路執行 X 視窗應用程式時,必須將滑鼠移動傳送到遠端計算機。(X 視窗系統是大多數 UNIX 系統上使用的視窗系統。)將它們收集起來進行突發傳送會導致滑鼠游標移動不正常,這會使使用者不滿意。
另一個可能降低 TCP 效能的問題是愚蠢視窗綜合徵。當資料以大塊形式傳遞到傳送 TCP 實體,而接收方上的互動式應用程式一次讀取一個位元組的資料時,就會出現此問題。要了解此問題,請檢視下圖。最初,接收方上的 TCP 緩衝區已滿,傳送方知道這一點(即視窗大小為 0)。然後,互動式應用程式從 TCP 流中讀取一個字元。此操作使接收 TCP 很高興,因此它會向傳送方傳送一個視窗更新,表示可以傳送 1 個位元組。傳送方照辦,傳送 1 個位元組。緩衝區現在已滿,因此接收方確認了 1 位元組的段,但將視窗設定為 0。這種行為可以無限期地持續下去。
Clark 的解決方案是阻止接收方傳送 1 位元組的視窗更新。相反,它必須等待,直到它有足夠的可用空間並通告該空間。具體來說,接收方在能夠處理在建立連線時通告的最大段大小或其緩衝區為空一半之前,不應該傳送視窗更新,以較小者為準。
此外,傳送方也可以透過不傳送很小的段來提供幫助。相反,它應該嘗試等待,直到它在視窗中累積了足夠的空閒空間以傳送一個完整段,或者至少傳送一個包含接收方緩衝區大小一半的段(它必須從過去接收到的視窗更新模式中估計這個大小)。
Nagle 演算法和 Clark 對愚蠢視窗綜合徵的解決方案是互補的。Nagle 試圖解決由傳送應用程式以一次一個位元組的方式向 TCP 傳遞資料引起的問題。Clark 試圖解決接收應用程式一次一個位元組地從 TCP 中提取資料的問題。兩種解決方案都有效,可以協同工作。目標是傳送方不傳送小的段,接收方也不請求小的段。
接收 TCP 可以進一步提高效能,而不僅僅是以大單位進行視窗更新。與傳送 TCP 一樣,它也可以緩衝資料,因此它可以阻止來自應用程式的 READ 請求,直到它有一個大的資料塊可以提供。這樣做減少了對 TCP 的呼叫次數,從而減少了開銷。當然,它也會增加響應時間,但對於非互動式應用程式(如檔案傳輸)來說,效率可能比對單個請求的響應時間更重要。另一個接收方問題是:如何處理亂序段。它們可以保留或丟棄,由接收方決定。當然,只有在接收了所有直到被確認的位元組的資料後,才能傳送確認。如果接收方收到段 0、1、2、4、5、6 和 7,它可以確認直到段 2 中最後一個位元組的所有資料。當傳送方超時時,它會重新傳輸段 3。如果接收方緩衝了段 4 到 7,在收到段 3 後,它可以確認直到段 7 末尾的所有位元組。
建立連線
只有當兩臺機器之間不存在連線、兩臺機器都同意連線,並且兩臺機器都具有足夠的 TCP 資源來為連線提供服務時,才能在兩臺機器之間建立連線。如果其中任何一個條件不滿足,則無法建立連線。應用程式或系統管理例程可以觸發連線的接受。
當建立連線時,它將獲得某些屬性,這些屬性在連線關閉之前有效。通常,這些屬性將是優先順序值和安全值。當連線正在建立過程中時,這兩個應用程式會商定這些設定。
在大多數情況下,兩個應用程式都會期望一個連線,因此它們會發出主動或被動開啟請求。下圖顯示了 TCP 開啟的流程圖。該過程從機器 A 的 TCP 接收來自其 ULP 的連線請求開始,它向機器 B 傳送一個主動開啟原語。構造的段將具有設定的 SYN 標誌(設定為 1)並將分配一個序列號。圖中使用 SYN SEQ 50 表示 SYN 標誌已開啟,序列號(初始傳送序列號或 ISS)為 50。(可以隨意選擇任何數字。)
機器 B 上的應用程式將已經向其 TCP 發出了被動開啟指令。當收到 SYN SEQ 50 段時,機器 B 的 TCP 將向機器 A 傳送一個確認,序列號為 51。機器 B 還將設定其自身的初始傳送序列號。圖中將此訊息顯示為 ACK 51; SYN 200 表示該訊息是一個確認訊息,序列號為 51,它具有設定的 SYN 標誌,並且 ISS 為 200。
收到後,機器 A 會將其自己的確認訊息傳送回,並將序列號設定為 201。圖中顯示為 ACK 201。然後,機器 A 和機器 B 都透過 ULP 向請求的應用程式傳送連線開啟訊息,從而開啟並確認了連線。
如前所述,遠端機器不需要有被動開啟指令。在這種情況下,傳送機器將提供傳送和接收套接字號,以及優先順序、安全性和超時值。兩個應用程式同時請求主動開啟是常見的。這很容易解決,儘管這確實會涉及更多網路流量。
資料傳輸
資訊傳輸過程非常簡單,如下圖所示。對於從 ULP 收到的每個資料塊,機器 A 的 TCP 會對其進行封裝,並將其傳送到機器 B,並附帶一個遞增的序列號。機器 B 接收訊息後,會用一個段確認訊息進行確認,該訊息會遞增下一個序列號(因此表明它收到了所有到該序列號為止的訊息)。圖中只顯示了單向傳輸的一個資訊段。
TCP 資料傳輸服務實際上包含六種不同的子服務
全雙工:允許連線的兩端在任何時間,甚至同時進行傳輸。
及時性:使用計時器確保資料在合理的時間內傳輸。
有序:從一個應用程式傳送的資料將在另一端按相同順序接收。即使資料報可能透過 IP 以亂序的方式接收,也會發生這種情況,因為 TCP 會在將訊息傳遞到更高層之前,以正確的順序重新組裝訊息。
標記:所有連線都具有商定的優先順序和安全值。
流量控制:TCP 可以透過使用緩衝區和視窗限制來調節資訊流。
錯誤校正:校驗和確保資料無誤(在校驗和演算法的限制範圍內)。
關閉連線
要關閉連線,其中一個 TCP 會從 ULP 接收一個關閉原語,併發出一個訊息,並將 FIN 標誌設定為開啟。如下圖 8 所示。在該圖中,機器 A 的 TCP 用下一個序列號向機器 B 傳送關閉連線的請求。機器 B 隨後會發送一個對請求的確認及其下一個序列號。在此之後,機器 B 透過其 ULP 將關閉訊息傳送到應用程式,並等待應用程式確認關閉。此步驟並非嚴格必要;TCP 可以不經應用程式批准就關閉連線,但一個行為良好的系統會將狀態更改告知應用程式。
在從應用程式接收到關閉連線的批准(或請求超時後),機器 B 的 TCP 會向機器 A 傳送一個帶有 FIN 標誌的段。最後,機器 A 確認關閉,連線終止。
當一方關閉套接字時,可能會發生連線的突然終止。這可以在不通知另一臺機器的情況下進行,也不考慮兩臺機器之間正在傳輸的任何資訊。除了由於故障或電源故障造成的突然關閉外,突然終止還可以由使用者、應用程式或判斷連線值得終止的系統監視程式啟動。連線的另一端可能直到嘗試傳送訊息並且計時器超時時才會意識到發生了突然終止。
為了跟蹤所有連線,TCP 使用連線表。每個現有連線在表中都有一個條目,顯示有關端到端連線的資訊。下面顯示了 TCP 連線表的佈局。
各列的含義如下
狀態:連線狀態(關閉、正在關閉、監聽、等待等)。
本地地址:連線的 IP 地址。處於監聽狀態時,這將設定為 0.0.0.0。
本地埠:本地埠號。
遠端地址:遠端主機的 IP 地址。
遠端埠:遠端連線的埠號。
TCP 重傳和超時
[edit | edit source]我們知道 TCP 提供可靠的資料傳輸。但是,它如何知道何時重傳已傳輸的包。確實,接收方會用下一個預期的序列號確認接收到的包。但是,如果傳送方沒有收到任何 ACK,該怎麼辦?
考慮以下兩種情況
未收到 ACK:在這種情況下,接收方會傳輸累積 ACK,但該幀在傳輸過程中丟失。傳送方通常會在從其緩衝區中重新整理已傳送的包之前等待此累積 ACK。但是,為此,它必須開發一些機制,以便傳送方可以在很長時間內未收到 ACK 時採取一些措施。這裡用於此目的的機制是計時器。TCP 在傳輸包時立即設定計時器。如果在超時之前收到 ACK,則 TCP 會從其緩衝區中重新整理這些包以騰出空間。如果在超時之前未收到 ACK,則 TCP 會再次重傳該包。但從哪裡選擇此超時間隔呢?我們將很快看到查詢該過程的步驟。
收到重複 ACK:在這種情況下,接收方會多次向傳送方傳送同一個接收到的包的 ACK。但是,您有沒有想過這怎麼會發生?嗯,這種事情可能會由於網路問題在某些時候發生,但是如果接收方多次(2-3 次以上)收到 ACK,那麼這將具有一定的意義。所有這些問題都始於接收方。接收方會一直向接收到的幀傳送 ACK。此 ACK 是累積性的。這意味著接收方有一個緩衝區。用於傳送累積 ACK 的演算法可能取決於緩衝區區域的填充量或剩餘量,或者可能取決於計時器。通常,會設定計時器,以便在特定時間間隔後,接收方會發送累積 ACK。但如果傳送方速率非常高怎麼辦?在這種情況下,接收方緩衝區會變滿,然後它將無法再儲存來自發送方的任何包。在這種情況下,接收方會一直髮送重複 ACK,這意味著緩衝區已滿,並且此後不會再接受任何包。此訊息有助於傳送方控制流速率。
整個過程使 TCP 成為一個自適應流量控制協議。這意味著在發生擁塞時,TCP 會調整其流速率。有關這方面的更多內容將在擁塞控制主題中介紹。此外,TCP 中沒有負 ACK。以上兩種情況會向傳送方傳達有關接收方狀態的正確資訊。現在讓我們重點關注 TCP 如何選擇超時間隔。
選擇超時間隔
計時器是根據包從傳送方到接收方完成往返所需的時間選擇的。此往返時間稱為 RTT。但條件,即 RTT 不會始終保持相同。實際上,RTT 會隨著時間的推移而發生很大變化。因此,需要將一些平均值包含到超時間隔的計算中。以下步驟將被執行。
1. 基於先前的結果計算平均 RTT(執行平均值)。
2. 測量該特定時間的 RTT,該值取決於當時的網路條件和擁塞情況(測量值)。
3. 計算超時間隔
0.8*(Running avg. ) + (1- 0.8)*(Measured)
值 0.8 可以根據需要更改,但必須小於 1。
4. 為了獲得更準確的結果,可以重複此過程多次。
因此,我們現在已經獲得了包完成往返所需的平均時間。為了選擇超時間隔,需要將該值乘以某個因子,以留出一些餘地。
5. 因此,
超時間隔 = 2 * (步驟 4 中獲得的值)
如果我們繼續繪製執行平均值和該特定時間的測量值的圖表,我們會發現執行平均值幾乎保持不變,而測量值波動較大。下面是針對這兩個值繪製的圖表。這解釋了為什麼執行平均值乘以的值大於用於乘以測量時間的的值。
比較:TCP 和 UDP
[edit | edit source]使用者資料報協議 (UDP) 和傳輸控制協議 (TCP) 是 TCP/IP 協議套件中傳輸層的“兄弟”。它們執行相同的角色,為應用程式和網際網路協議 (IP) 的資料移動功能提供介面,但它們以非常不同的方式執行此操作。因此,這兩個協議為更高層的協議提供了選擇,允許每個協議根據其需要選擇合適的協議。
下表有助於說明這兩個協議最重要的基本屬性以及它們之間的對比
練習題
[edit | edit source]這裡的練習題包括作業題以及答案。這將有助於學生掌握 TCP 的概念,並鼓勵他們從 Kurose 和 Tanenbaum 的書中做更多練習題。
1) UDP 和 TCP 使用 1 的補碼來進行校驗和計算。假設您有以下三個 8 位位元組:01010101、01110000、01001100。這些 8 位位元組的和的 1 的補碼是多少?(注意,雖然 UDP 和 TCP 在計算校驗和時使用 16 位字,但在這個問題中,您被要求考慮 8 位加數。)顯示所有步驟。為什麼 UDP 對總和取 1 的補碼;也就是說,為什麼不直接使用總和呢?在 1 的補碼方案中,接收方如何檢測錯誤?一個位的錯誤有可能不被檢測到嗎?兩個位的錯誤呢?
解答: 01010101 + 01110000 + 11000101 = 110001010
10001010 的 1 的補碼 = 校驗和 = 01110101。
在接收端,將 3 個訊息和校驗和加在一起以檢測錯誤。總和應該始終只包含二進位制 1。如果總和包含 0 項,則接收方知道存在錯誤。接收方將檢測到 1 位錯誤。但對於 2 位錯誤,情況可能並非總是如此,因為兩個不同的位可能會改變,但總和可能仍然相同。
2) 對以下問題回答“正確”或“錯誤”,並簡要說明您的答案
a) 使用 SR 協議,傳送方有可能收到對超出其當前視窗的包的 ACK。
正確。考慮以下情況:傳送方傳送的第一個包沒有收到 ACK,因為計時器已過期。因此,它會再次傳送該包。在此期間,會收到第一個包的 ACK。因此,傳送方清空其緩衝區,並用新包填充緩衝區。與此同時,可能會收到第二個幀的 ACK。因此,即使包超出當前視窗,也可能會收到 ACK。
b) 使用 GBN,傳送方有可能收到對超出其當前視窗的包的 ACK。
正確。與 (a) 中提供的相同論據在此處適用。
c) 交替位協議與傳送方和接收方視窗大小為 1 的 SR 協議相同。
正確。交替位協議將 0 和 1 作為交替 ACK。這裡,累積 ACK 不可能,因為每個包接收後都需要傳送 ACK。因此,SR 協議開始表現得像交替位協議。
d) 交替位協議與傳送方和接收方視窗大小為 1 的 GBN 協議相同。
正確。相同的論據在此處適用。
3) 考慮用於估計 RTT 的 TCP 位置。假設 a=0.1,令樣本 RTT1 為最新的樣本 RTT,令樣本 RTT2 為次最新的樣本 RTT,依此類推。
a) 對於給定的 TCP 連線,假設已返回四個確認,對應樣本 RTT 分別為樣本 RTT4、樣本 RTT3、樣本 RTT2、樣本 RTT1。用四個樣本 RTT 表示估計的 RTT。
b) 將您的公式推廣到 n 個樣本 RTT。
c) 對於 (b) 部分的公式,令 n 趨於無窮大。解釋為什麼這種平均過程稱為指數移動平均。
解決方案
a)
估計的 RTT1 = 樣本 RTT1
估計的 RTT2 = (1-a) 估計的 RTT1 + a 樣本 RTT2 = (1-a) 樣本 RTT1 + a 樣本 RTT2
估計的 RTT3 = (1-a) 估計的 RTT2 + a 樣本 RTT3 = (1-a)2 樣本 RTT1 + (1-a)a 樣本 RTT2 + a 樣本 RTT3''
估計的 RTT4 = (1-a) 估計的 RTT3 + a 樣本 RTT4 = (1-a)3 樣本 RTT1 + (1-a)2a 樣本 RTT2 + (1-a)a 樣本 RTT3 + a 樣本 RTT4
b)
估計的 RTTn = (1-a)(n-1) 樣本 RTT1 + (1-a)(n-2)a 樣本 RTT2 + (1-a)(n-3)a 樣本 RTT3 +... (1-a)a 樣本 RTTn-1 + a 樣本 RTTn
4) 我們從文字中瞭解到,TCP 在收到三個重複的 ACK 後才會執行快速重傳。您認為 TCP 設計人員為什麼選擇不在收到第一個重複的 ACK 後執行快速重傳?
解決方案:假設傳送方傳送了 3 個連續的資料包 1、2 和 3。接收方收到 1 後,立即傳送對它的 ACK。假設接收方收到 3 而不是 2,原因是亂序。由於接收方尚未收到 2,因此再次傳送對 1 的 ACK。因此,傳送方收到了對 1 的第二個 ACK。儘管如此,它仍然繼續等待。現在接收方收到 2 時,傳送 ACK 2,然後傳送 ACK 3。因此,在重傳資料包之前等待超過 2 個 ACK 始終是安全的。
5) 您認為 TCP 為什麼避免為重傳段測量樣本 RTT?
解決方案:讓我們看看如果 TCP 測量重傳段的樣本 RTT 會出現什麼問題。假設源傳送資料包 P1,P1 的計時器超時,然後源傳送 P2,這是同一個資料包的新副本。假設源測量 P2(重傳資料包)的樣本 RTT。最後假設在傳送 P2 後不久,收到對 P1 的確認。源將錯誤地將此確認視為對 P2 的確認,並計算出不正確的樣本 RTT 值。

