1. 程式人生 > 實用技巧 >計算機網路05:傳輸層

計算機網路05:傳輸層

目錄

計算機網路:傳輸層

- 應用層協議:http、https、ftp、dns、smtp、pop3、rdp、telnet、……
  • 傳輸層協議:TCP、UDP

  • 網路層協議:IP(RIP、OSPF、BGP)、ARP、ICMP、IGMP

5.1、傳輸層的兩個協議

傳輸層也稱為運輸層。

5.1.1、概述

程序之間的通訊

  • 從通訊和資訊處理的角度看,傳輸層向它上面的應用層提供通訊服務,它屬於面向通訊部分的最高層,同時也是使用者功能中的最低層。
  • 當網路的邊緣部分中的兩個主機使用網路的核心部分的功能進行端到端的通訊時,只有位於網路邊緣部分的主機的協議棧才有傳輸層,而網路核心部分中的路由器在轉發分組時都只用到下三層的功能。

運輸層為相互通訊的應用程序提供了邏輯通訊

  • 兩個主機進行通訊實際上就是兩個主機中的應用程序互相通訊
  • 應用程序之間的通訊又稱為端到端的通訊
  • 運輸層的一個很重要的功能就是複用分用。應用層不同程序的報文通過不同的埠向下交到運輸層,再往下就共用網路層提供的服務。
  • “運輸層提供應用程序間的邏輯通訊”。“邏輯通訊”的意思是:運輸層之間的通訊好像是沿水平方向傳送資料。但事實上這兩個運輸層之間並沒有一條水平方向的物理連線。

運輸層協議和網路層協議的主要區別

運輸層協議和網路層協議的主要區別

  • 運輸層為應用程序之間提供端到端的邏輯通訊(但網路層是為主機之間提供邏輯通訊)
  • 運輸層還要對收到的報文進行差錯檢測
  • 運輸層需要有兩種不同的運輸協議,即面向連線的 TCP 和無連線的 UDP
  • 運輸層的 UDP 使用者資料報與網際層的 IP 資料報有很大區別。IP 資料報要經過互連網中許多路由器的儲存轉發,但 UDP 使用者資料報是在運輸層的端到端抽中象的邏輯通道中傳送的。

兩種不同的運輸協議

  • 運輸層向高層使用者遮蔽了下面網路核心的細節(如網路拓撲、所採用的路由選擇協議等),它使應用程序看見的就是好像在兩個運輸層實體之間有一條端到端的邏輯通訊通道。
  • 當運輸層採用面向連線的 TCP 協議時,儘管下面的網路是不可靠的(只提供盡最大努力服務),但這種邏輯通訊通道就相當於一條全雙工的可靠通道。
  • 當運輸層採用無連線的 UDP 協議時,這種邏輯通訊通道是一條不可靠通道。

5.1.2、TCP & UDP 協議的應用場景

網路中的計算機通訊無外乎有以下兩種情況:

  1. 要傳送的內容多,需要將傳送的內容分成多個數據包傳送。
  2. 要傳送的內容少,一個數據包就能傳送全部內容。

針對這兩種情況,在傳輸層有兩個協議:

  1. TCP(Transmission Control Protocol,傳輸控制協議)
  2. UDP(User Datagram Protocol,使用者資料報協議)

TCP:分段,編號,流量控制,建立會話

UDP:一個數據包就能完成資料通訊,不建立會話,多播

TCP & UDP 的關係

  • 兩個對等運輸實體在通訊時傳送的資料單位叫作運輸協議資料單元 TPDU (Transport Protocol Data Unit)
  • TCP 傳送的資料單位是 TCP 報文段(segment)
  • UDP 傳送的資料單位是 UDP 報文 or 使用者資料報

幾點注意:

  • UDP 在傳送資料之前不需要建立連線。對方的傳輸層在收到 UDP 報文後,不需要給出任何確認。雖然 UDP 不提供可靠交付,但在某些情況下,UDP 是一種最有效的工作方式。

  • TCP 則是面向連線的服務。TCP 不提供廣播或多播服務。由於 TCP 要提供可靠的、面向連線的傳輸服務,因此不可避免地增加了許多的開銷。這不僅使協議資料單元的首部增大很多,還要佔用許多的處理機資源。

  • TCP 報文段是在運輸層抽象的端到端邏輯通道中傳送,這種通道是可靠的全雙工通道。但這樣的通道卻不知道究竟經過了哪些路由器,而這些路由器也根本不知道上面的運輸層是否建立了 TCP 連線。


5.1.3、傳輸層的埠

  • 執行在計算機中的程序是用程序識別符號來標誌的。
  • 執行在應用層的各種應用程序卻不應當讓計算機作業系統指派它的程序識別符號。這是因為在因特網上使用的計算機的作業系統種類很多,而不同的作業系統又使用不同格式的程序識別符號。
  • 為了使執行不同作業系統的計算機的應用程序能夠互相通訊,就必須用統一的方法對 TCP/IP 體系的應用程序進行標誌。

需要解決的問題

  1. 由於程序的建立和撤銷都是動態的,傳送方几乎無法識別其他機器上的程序。
  2. 有時我們會改換接收報文的程序,但並不需要通知所有傳送方。
  3. 我們往往需要利用目的主機提供的功能來識別終點,而不需要知道實現這個功能的程序。

解決這個問題的方法就是在運輸層使用協議埠號(protocol port number),或通常簡稱為 埠(port)

  • 埠用一個 16 位埠號進行標誌。

  • 埠號只具有本地意義,即埠號只是為了標誌本計算機應用層中的各程序。在因特網中不同計算機的相同埠號是沒有聯絡的。

雖然通訊的終點是應用程序,但我們可以把埠想象是通訊的終點,因為我們只要把要傳送的報文交到目的主機的某一個合適的目的埠,剩下的工作(即最後交付目的程序)就由 TCP 來完成。

軟體埠與硬體埠

  • 在協議棧層間的抽象的協議埠是軟體埠
  • 路由器或交換機上的埠是硬體埠
  • 硬體埠是不同硬體裝置進行互動的介面,而軟體埠是應用層的各種協議程序與運輸實體進行層間互動的一種地址。

埠的分類

按埠號可分為 3 大類:

  1. 熟知埠(Well Known Ports):數值一般為 0~1023。例如:80 埠實際上總是 HTTP 通訊。
  2. 註冊埠(Registered Ports):從 1024 到 49151。它們鬆散地綁定於一些服務。也就是說有許多服務綁定於這些埠,這些埠同樣用於許多其它目的。例如:許多系統處理動態埠從 1024 左右開始。
  3. 動態和 / 私有埠(Dynamic and/or Private Ports):從 49152 到65535。理論上,不應為服務分配這些埠。實際上,機器通常從 1024起分配動態埠。但也有例外:SUN 的 RPC 埠從 32768 開始。

5.1.4、傳輸層協議和應用層協議之間的關係

  • FTP = TCP + 21
  • SSH = TCP + 22
  • Telnet = TCP + 23
  • SMTP = TCP + 25
  • DNS = UDP + 53 or TCP(很少) + 53
  • HTTP= TCP + 80
  • POP3 = TCP + 110
  • HTTPS = TCP + 443
  • 共享資料夾 = TCP + 445
  • SQL Server = TCP + 1433
  • MySQL = TCP + 3306
  • RDP = TCP + 3389

應用層協議和服務之間的關係:服務執行後會在 TCP or UDP 的某個埠一直偵聽客戶端請求(對外提供的服務偵聽,對內提供的服務不偵聽)

埠代表服務,用埠區分服務

更改埠有利於增加伺服器安全

5.1.5、網路安全知識


Windows 10 系統開啟 telnet 服務

# 開啟控制面板
control
# 開啟 微軟終端服務客戶端,Microsoft terminal services client
mstsc
# 開啟防火牆的高階設定
wf.msc
# 開啟服務
services.msc
# 開啟系統配置實用程式
msconfig



# 測試遠端計算機開啟的埠
telnet 192.s168.2.116 21


Windows 10 防火牆的作用

當啟用 Windows 10 防火牆阻止所有傳入連線時,會把所有的埠都關閉,Windows 10 防火牆不攔截出去的流量,但攔截主動進來的流量,出去的流量還可以回來,埠是動態開啟和關閉的,此時,你的計算機就相當於在網際網路上隱身了,但還可以訪問外網,可以防止別人掃描你的埠來攻擊你計算機上安裝的服務。

開啟 Windows 10 防火牆 阻止所有傳入連線操作步驟:

第一步:開啟控制面板 --> 點選 系統和安全

第二步:點選 Windows Defender 防火牆


第三步:測試:

① 讓另一臺計算機 ping 本計算機的 IP 地址,發現 ping 不通

② 本計算機 ping www.baidu.com 可以 ping 通

取消勾選時,發現可以 ping 通了!


灰鴿子木馬

一般來說,是客戶端主動連線伺服器,但木馬程式是木馬服務主動連線客戶端,如果計算機一旦中了木馬,Windows 防火牆不能防控木馬程式!

Windows 系統可以指定 安全策略,例如可以讓主動進入且目標埠為 80 進,讓出去且源埠為 80 的出,這時木馬就只是一段執行著的程式碼,無法與外界客戶端取得連線,被堵在裡
面,沒有威脅!



5.2、使用者資料報協議 UDP

5.2.1、UDP 協議的特點

1)、UDP 是無連線的,即傳送資料之前不需要建立連線(當然傳送資料結束時也沒有連線可釋放),因此減少了開銷和傳送資料之前的時延。
2)、UDP 使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持複雜的連線狀態表(這裡面有許多引數),通訊的兩端不用保持連線,因此節省系統資源。
3)、UDP 是面向報文的,傳送方的 UDP 對應用程式交下來的報文,在新增首部後就向下交付給網路層。UDP 對應用層交下來的報文,既不合並,也不拆分,而是保留這些報文的邊界。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-W0VJs1iK-1596446046744)(計算機網路05:傳輸層.assets/image-20200801145940333.png)]

4)、UDP 沒有擁塞控制,即使網路出現的擁塞也不會使源主機的傳送速率降低。這對某些實時應用是很重要的。
5)、UDP 支援一對一、一對多、多對一和多對多的互動通訊。
6)、UDP 的首部開銷小,只有 8 個位元組,比 TCP 的 20 個位元組的首部要短。


5.2.2、UDP 的首部格式

UDP 的首部包括四個欄位,每個欄位的長度是 2 個位元組,因此首部共 8 個 位元組。

  • 源埠:源埠號。在需要對方回信時選用。不需要時可用全 0
  • 目標埠:目的埠號。在終點交付報文時使用。
  • 長度:UDP 使用者資料報的長度,其最小值是 8(僅有首部)。
  • 校驗和:檢測 UDP 使用者資料報在傳輸中是否有錯。有錯就丟棄。

如果接收方 UDP 發現收到的報文中的目的埠號不正確(即不存在對應於該埠號的應用程序),就丟棄該報文,並由網際控制報文協議 ICMP 傳送“埠不可達”差錯報文給傳送方。

雖然在 UDP 之間的通訊要用到其埠號,但由於 UDP 的通訊是無連線的,因此不需要使用套接字(TCP 之間的通訊必須要在兩個套接字之間建立連線)。

UDP 使用者資料報首部中檢驗和的計算方法很特殊。

偽首部包括:源地址、目的地址、UDP資料長度、協議型別(0x11),協議型別就一個位元組,但需要在前補一個位元組的 0x0,構成 12 個位元組。

在計算檢驗和時,要在UDP 使用者資料報之前增加 12 個位元組的偽首部。所謂“偽首部”是因為這種偽首部並不是 UDP 使用者資料報的真正的首部。只是在計算檢驗和時臨時新增在UDP使用者資料報前面,得到一個臨時的 UDP 使用者資料報。

檢驗和就是按照這個臨時的 UDP 使用者資料報來計算的。偽首部既不向下傳送也不向上遞交,而僅僅是為了計算檢驗和


5.3、傳輸控制協議 TCP

  1. TCP 協議的特點?
  2. TCP 協議首部格式?
  3. TCP 協議是如何實現可靠傳輸?
  4. TCP 協議是如何實現流量控制?
  5. TCP 協議是如何避免網路擁塞?

5.3.1、TCP 協議特點

  • TCP 是面向連線的傳輸層協議。

    • 在傳送資料完畢後,必須釋放已經建立的 TCP 連線。這就是說,應用程序之間的通訊好像在“打電話”:通話前要先撥號建立連線,通話結束後要掛機釋放連線。

    • 每一條 TCP 連線只能有兩個端點(endpoint),每一條 TCP 連線只能是點對點的(一對一,單播)。

  • TCP 提供可靠交付的服務。

  • 也就是說,通過 TCP 連線傳送的資料,無差錯、不丟失、不重複、且按序傳送。

  • TCP 提供全雙工通訊。

    • TCP 允許通訊雙方的應用程序可以同時傳送和接受資料。
    • TCP 連線的兩端都設有 TCP 傳送快取TCP 接收快取,用來臨時存放雙向通訊的資料。
    • 在傳送時,應用程式把即將傳送的資料傳送到給 TCP 傳送快取後,就可以做自己的事,而 TCP 在合適的時候把資料傳送出去。
    • 在接收時,TCP 把收到的資料放入 TCP 接受快取中,上層的應用程序在合適的時候讀取快取中的資料。
  • 面向位元組流。

    • TCP 中的“流”(steam)指的是 流入到程序 或 從程序流出的位元組 序列。

注意:

  • TCP 連線是一條虛連線而不是一條真正的物理連線。
  • TCP 對應用程序一次把多長的報文傳送到 TCP 的快取中是不關心的。
  • TCP 根據對方給出的視窗值當前網路擁塞的程度來決定一個報文段應包含多少個位元組(UDP 傳送的報文長度是應用程序給出的)。
  • TCP 可把太長的資料塊劃分短一些再傳送。
  • TCP 也可等待積累有足夠多的位元組後再構成報文段傳送出去。

TCP 的連線

  • TCP 把連線作為最基本的抽象。

  • 每一條 TCP 連線有兩個端點。TCP 連線的端點叫做 套接字(socket)或插口。

  • TCP 連線的端點不是主機,不是主機的 IP 地址,不是應用程序,也不是傳輸層的協議埠。而是 IP 地址 + 埠。

  • 每一條 TCP 連線唯一地被通訊兩端的兩個端點(即套接字)所確定。


5.3.2、TCP 首部格式

TCP 協議是能夠實現資料分段傳輸、可靠傳輸、流量控制、網路擁塞避免等功能,因此 TCP 報文的首部要比 UDP 報文首部欄位要多,並且首部長度不固定。

TCP 報文段中各欄位的意義

  • 源埠(Source Port):佔 2 個位元組

  • 目標埠(Destination Port):佔 2 個位元組

  • 序號(Sequence number,seq):佔 4 個位元組,傳送的資料部分(段)的第一個位元組的位置

  • 確認號(Acknowledgment number,ack):佔 4 個位元組,告訴傳送者下一次該發第幾個位元組了

序號欄位和確認欄位的意義
  • 資料偏移(即首部長度):佔 4 位,記錄 TCP 報文段從多少個位元組以後就開始有資料了
    • 因為 TCP 報文段的首部有固定部分(前 20 個位元組),也有可選部分,所以要用資料偏移來標記從多少個位元組開始就是資料了。
  • 保留:佔 6 位,保留為今後使用,但目前應置為 0。
  • 標誌位(Flags):

  • 視窗(Window size value):佔 2 位元組。視窗值是 [0,216-1] 之間的整數。TCP 協議有流量控制功能,視窗值告訴對方:從本報文段首部中的確認號算起,接收方目前允許對方傳送的資料量(單位是位元組)。

  • 檢驗和(Check sum):佔 2 位元組。檢驗和欄位檢驗的範圍包括首部和資料這兩部分。和 UDP 使用者資料報一樣,在計算檢驗和時,要在 TCP 報文段的前面加上 12 位元組的偽首部。

  • 緊急指標(Urgent pointer):佔 2 位元組。緊急指標僅在 URG = 1 時才有意義,它指出本報文段中的緊急資料的位元組數(緊急資料結束後就是普通資料)。因此緊急指標指出了緊急資料的下一個位元組在報文段中的位置。

  • 選項(Options):長度可變,最長可達 40 個位元組。當沒有使用選項時,TCP 的首部長度是 20 位元組。

    • TCP 最初只規定了一種選項,即最大報文段長度 MSS(Maximum Segment Size)。
    • MSS 告訴對方 TCP:“我的快取所能接收的報文段的資料欄位的最大長度是 MSS 個位元組。”
    • MSS (Maximum Segment Size) 是 TCP 報文段中的資料欄位的最大長度。
      資料欄位 + TCP 首部才等於整個的 TCP 報文段。
  • 填充欄位: 這是為了使整個首部長度是 4 位元組的整數倍。

其他選項

  • 視窗擴大選項:佔 3 位元組,其中有一個位元組表示移位值 S。新的視窗值等於 TCP 首部中的視窗位數增大到(16 + S),相當於把視窗值向左移動 S 位後獲得實際的視窗大小。
  • 時間戳選項:佔10 位元組,其中最主要的欄位時間戳值欄位(4 位元組)和時間戳回送回答欄位(4 位元組)。
  • 選擇確認選項

5.4、可靠傳輸的工作原理

網路層是不可靠的,只負責把一個數據包從一個網段轉到另外一個網段,資料包丟了是不管的,可靠傳輸是由傳輸層實現的。

5.4.1、停止等待協議

  1. 在傳送完一個分組後,必須暫時保留已傳送的分組的副本。
  2. 分組和確認分組都必須進行編號。
  3. 超時計時器的重傳時間應當比資料在分組傳輸的平均往返時間更長一些。

只要你沒有告訴我你收到了,我就認為你沒收到,我就重傳

使用上述的確認和重傳機制,我們就可以在不可靠的傳輸網路上實現可靠的通訊。

這種可靠傳輸協議常稱為:[自動重傳請求](ARQ,Automatic Repeat reQuest)

ARQ 表明重傳的請求是[自動]進行的。接收方不需要請求傳送方重傳某個出錯的分組。

通道利用率

  • 停止等待協議的優點是簡單,但缺點是通道利用率太低。

\(通道利用率:U = \frac{T_D}{T_D + RTT + T_A}\)

流水線傳輸

  • 傳送方可連續傳送多個分組,不必每發完一個分組就停頓下來等待對方的確認。
  • 由於通道上一直有資料不間斷地傳送,這種傳輸方式可獲得很高的通道利用率。


5.4.2、連續的 ARQ 協議

累積確認

  • 接收方一般採用 累積確認 的方式。即不必對收到的分組逐個傳送確認,而是對按序到達且連續的最後一個分組傳送確認,這樣就表示:到這個分組為止的所有分組都已正確收到了。

  • 累積確認有的優點是:容易實現

  • 缺點是:不能向傳送方反映出接收方已經正確收到的所有分組的資訊。

Go-back-N(回退 N)

  • 如果傳送方傳送了前 5 個分組,而中間的第 3 個分組丟失了。這時接收方只能對前兩個分組發出確認。
  • 傳送方無法知道後面三個分組的下落,而只好把後面的三個分組都再重傳一次。
  • 這就叫做 Go-back-N(回退 N),表示需要再退回來重傳已傳送過的 N 個分組。
  • 可見當通訊線路質量不好時,連續 ARQ 協議會帶來負面的影響。

TCP 可靠通訊的具體實現

  • TCP 連線的每一端都必須設有兩個視窗——一個傳送視窗和一個接收視窗
  • TCP 的可靠傳輸機制用位元組的序號進行控制。TCP 所有的確認都是基於序號而不是基於報文段。
  • TCP 兩端的四個視窗經常處於動態變化之中。
  • TCP連線的往返時間 RTT 也不是固定不變的。需要使用特定的演算法估算較為合理的重傳時間。

5.5、可靠傳輸的具體實現

5.5.1、以位元組為單位的滑動視窗技術



傳送快取與接收快取的作用

  • 傳送快取用來暫時存放:
    • 傳送應用程式傳送給傳送方 TCP 準備傳送的資料;
    • TCP 已傳送出但尚未收到確認的資料。
  • 接收快取用來暫時存放:
    • 按序到達的、但尚未被接收應用程式讀取的資料;
    • 不按序到達的資料。

注意:

  1. A 的傳送視窗並不總是和 B 的接收視窗一樣大(因為有一定的時間滯後)。
  2. TCP 標準沒有規定對不按序到達的資料應如何處理。通常是先臨時存放在接收視窗中,等到位元組流中所缺少的位元組收到後,再按序交付上層的應用程序。
  3. TCP 要求接收方必須有累積確認的功能,這樣可以減小傳輸開銷。

5.5.2、超時重傳時間的選擇

  • 重傳機制是 TCP 中最重要和最複雜的問題之一。
  • TCP 每傳送一個報文段,就對這個報文段設定一次計時器。只要計時器設定的重傳時間到但還沒有收到確認,就要重傳這一報文段。

往返時延的方差很大

由於 TCP 的下層是一個網際網路環境,IP 資料報所選擇的路由變化很大。因而運輸層的往返時間的方差也很大。

加權平均往返時間 \(RTT_s\)

  • TCP 保留了 RTT 的一個加權平均往返時間 RTTS(這又稱為平滑的往返時間)。
  • 第一次測量到 RTT 樣本時,RTTS 值就取為所測量到的 RTT 樣本值。以後每測量到一個新的 RTT 樣本,就按下式重新計算一次 RTTS:

\(新的 RTT_s = (1 - α) × (舊的 RTT_s) + α × (新的 RTT 樣本)\)

  • 式中, \(0 ≤ α <1\)
  • 若 α 很接近於零,表示 RTT 值更新較慢。
  • 若選擇 α 接近於 1,則表示 RTT 值更新較快。
  • RFC 2988 推薦的 α 值為 1/8,即 0.125。

超時重傳時間 \(RTO\) (RetransmissionTime-Out)

  • \(RTO\) 應略大於上面得出的加權平均往返時間 \(RTT_S\)
    • RFC 2988 建議使用下式計算 RTO:\(RTO = RTTS + 4 × RTT_D\)
  • \(RTT_D\)\(RTT\) 的偏差的加權平均值。
  • RFC 2988 建議這樣計算 \(RTT_D\) 。第一次測量時,\(RTT_D\) 值取為測量到的 \(RTT\) 樣本值的一半。在以後的測量中,則使用下式計算加權平均的 \(RTT_D:\)
    • $新的 RTT_D = (1 - β) × (舊的 RTT_D) + β × | RTT_s - 新的 RTT 樣本 | $
    • β 是個小於 1 的係數,其推薦值是 1/4,即 0.25。

往返時間的測量相當複雜

  • TCP 報文段 1 沒有收到確認。重傳(即報文段 2)後,收到了確認報文段 ACK。
  • 如何判定此確認報文段是對原來的報文段 1 的確認,還是對重傳的報文段 2 的確認?

Karn 演算法

  • 在計算平均往返時間 RTT 時,只要報文段重傳了,就不採用其往返時間樣本。
  • 這樣得出的加權平均平均往返時間 \(RTT_S\) 和超時重傳時間 \(RTO\) 就較準確。

修正的 Karn 演算法

  • 報文段每重傳一次,就把 RTO 增大一些:
    • $新的 RTO = γ × (舊的 RTO) $
    • 係數 γ 的典型值是 2 。
  • 當不再發生報文段的重傳時,才根據報文段的往返時延更新平均往返時延 \(RTT\) 和超時重傳時間 \(RTO\) 的數值。
  • 實踐證明,這種策略較為合理。

5.5.3、選擇確認 SACK(Selective ACK)

  • 接收方收到了和前面的位元組流不連續的兩個位元組塊。
  • 如果這些位元組的序號都在接收視窗之內,那麼接收方就先收下這些資料,但要把這些資訊準確地告訴傳送方,使傳送方不要再重複傳送這些已收到的資料。

RFC 2018 的規定

  • 如果要使用選擇確認,那麼在建立 TCP 連線時,就要在 TCP 首部的選項中加上“允許 SACK”的選項,而雙方必須都事先商定好。
  • 如果使用選擇確認,那麼原來首部中的“確認號欄位”的用法仍然不變。只是以後在 TCP 報文段的首部中都增加了 SACK 選項,以便報告收到的不連續的位元組塊的邊界。
  • 由於首部選項的長度最多隻有 40 位元組,而指明一個邊界就要用掉 4 位元組,因此在選項中最多隻能指明 4 個位元組塊的邊界資訊。

5.6、TCP 的流量控制

流量控制解決的是通訊兩端處理速度不一致問題的!

流量控制是通過接收端告訴傳送端接收視窗的大小來控制的!

5.6.1、利用滑動視窗實現流量控制

持續計時器 (persistence timer)

  • TCP 為每一個連線設有一個持續計時器
  • 只要 TCP 連線的一方收到對方的零視窗通知,就啟動持續計時器。
  • 若持續計時器設定的時間到期,就傳送一個零視窗探測報文段(僅攜帶 1 位元組的資料),而對方就在確認這個探測報文段時給出了現在的視窗值。
  • 若視窗仍然是零,則收到這個報文段的一方就重新設定持續計時器。
  • 若視窗不是零,則死鎖的僵局就可以打破了。

5.6.2、必須考慮傳輸效率

可以用不同的機制來控制 TCP 報文段的傳送時機:

  1. 第一種機制是 TCP 維持一個變數,它等於最大報文段長度 MSS。只要快取中存放的資料達到 MSS 位元組時,就組裝成一個 TCP 報文段傳送出去。
  2. 第二種機制是由傳送方的應用程序指明要求傳送報文段,即 TCP 支援的推送(push)操作。
  3. 第三種機制是傳送方的一個計時器期限到了,這時就把當前已有的快取資料裝入報文段(但長度不能超過 MSS)傳送出去。

5.7、TCP 的擁塞控制

5.7.1、擁塞控制的一般原理

擁塞控制

  • 在某段時間,若對網路中某資源的需求超過了該資源所能提供的可用部分,網路的效能就要變壞——產生擁塞(congestion)。
  • 出現資源擁塞的條件: 對資源需求的總和 > 可用資源
  • 若網路中有許多資源同時產生擁塞,網路的效能就要明顯變壞,整個網路的吞吐量將隨輸入負荷的增大而下降。

擁塞控制與流量控制的關係

  • 擁塞控制所要做的都有一個前提,就是網路能夠承受現有的網路負荷。
  • 擁塞控制是一個全域性性的過程,涉及到所有的主機、所有的路由器,以及與降低網路傳輸效能有關的所有因素。
  • 流量控制往往指在給定的傳送端和接收端之間的點對點通訊量的控制。
  • 流量控制所要做的就是抑制傳送端傳送資料的速率,以便使接收端來得及接收。

擁塞控制所起的作用

開環控制和閉環控制

  • 開環控制方法就是在設計網路時事先將有關發生擁塞的因素考慮周到,力求網路在工作時不產生擁塞。
  • 閉環控制是基於反饋環路的概念。屬於閉環控制的有以下幾種措施:
    1. 監測網路系統以便檢測到擁塞在何時、何處發生。
    2. 將擁塞發生的資訊傳送到可採取行動的地方。
    3. 調整網路系統的執行以解決出現的問題。

5.7.2、幾種擁塞控制方法

1、慢開始和擁塞避免

傳送方維持一個叫做擁塞視窗 cwnd (congestion window) 的狀態變數。擁塞視窗的大小取決於網路的擁塞程度,並且動態地在變化。傳送方讓自己的傳送視窗等於擁塞視窗。如再考慮到接收方的接收能力,則傳送視窗還可能小於擁塞視窗。

傳送方控制擁塞視窗的原則是:只要網路沒有出現擁塞,擁塞視窗就再增大一些,以便把更多的分組傳送出去。但只要網路出現擁塞,擁塞視窗就減小一些,以減少注入到網路中的分組數。

慢開始演算法的原理

  1. 在主機剛剛開始傳送報文段時可先設定擁塞視窗 cwnd = 1,即設定為一個最大報文段 MSS 的數值。
  2. 在每收到一個對新的報文段的確認後,將擁塞視窗加 1,即增加一個 MSS 的數值。
  3. 用這樣的方法逐步增大發送端的擁塞視窗 cwnd,可以使分組注入到網路的速率更加合理。


傳輸輪次 (transmission round)

  • 使用慢開始演算法後,每經過一個傳輸輪次,擁塞視窗 cwnd 就加倍。
    一個傳輸輪次所經歷的時間其實就是往返時間 RTT。
  • “傳輸輪次”更加強調:把擁塞視窗 cwnd 所允許傳送的報文段都連續傳送出去,並收到了對已傳送的最後一個位元組的確認。
  • 例如,擁塞視窗 cwnd = 4,這時的往返時間 RTT 就是傳送方連續傳送 4 個報文段,並收到這 4 個報文段的確認,總共經歷的時間。

設定慢開始門限狀態變數 ssthresh

ssthresh——慢啟動閾值

慢開始門限 ssthresh 的用法如下:

  1. 當 cwnd < ssthresh 時,使用慢開始演算法。
  2. 當 cwnd > ssthresh 時,停止使用慢開始演算法而改用擁塞避免演算法。
  3. 當 cwnd = ssthresh 時,既可使用慢開始演算法,也可使用擁塞避免演算法。

擁塞避免演算法的思路是讓擁塞視窗 cwnd 緩慢地增大,即每經過一個往返時間 RTT 就把傳送方的擁塞視窗 cwnd 加 1,而不是加倍,使擁塞視窗 cwnd 按線性規律緩慢增長。

無論在慢開始階段還是在擁塞避免階段,只要傳送方判斷網路出現擁塞(其根據就是沒有按時收到確認),就要把慢開始門限 ssthresh 設定為出現擁塞時的傳送方視窗值的一半(但不能小於2)。

然後把擁塞視窗 cwnd 重新設定為 1,執行慢開始演算法。

這樣做的目的就是要迅速減少主機發送到網路中的分組數,使得發生擁塞的路由器有足夠時間把佇列中積壓的分組處理完畢。

慢開始和擁塞避免演算法的實現舉例

當 TCP 連線進行初始化時,將擁塞視窗置為 1。圖中的視窗單位不使用位元組而使用報文段。

慢開始門限的初始值設定為 16 個報文段,即 ssthresh = 16。

傳送端的傳送視窗不能超過擁塞視窗 cwnd 和接收端視窗 rwnd 中的最小值。我們假定接收端視窗足夠大,因此現在傳送視窗的數值等於擁塞視窗的數值。

在執行慢開始演算法時,擁塞視窗 cwnd 的初始值為 1,傳送第一個報文段 M0。

傳送端每收到一個確認 ,就把 cwnd 加 1。於是傳送端可以接著傳送 M1 和 M2 兩個報文段。

接收端共發回兩個確認。傳送端每收到一個對新報文段的確認,就把傳送端的 cwnd 加 1。現在 cwnd 從 2 增大到 4,並可接著傳送後面的 4 個報文段。

傳送端每收到一個對新報文段的確認,就把傳送端的擁塞視窗加 1,因此擁塞視窗 cwnd 隨著傳輸輪次按指數規律增長。


當擁塞視窗 cwnd 增長到慢開始門限值 ssthresh 時(即當 cwnd = 16 時),就改為執行擁塞避免演算法,擁塞視窗按線性規律增長。

假定擁塞視窗的數值增長到 24 時,網路出現超時,表明網路擁塞了。

更新後的 ssthresh 值變為 12(即傳送視窗數值 24 的一半),擁塞視窗再重新設定為 1,並執行慢開始演算法。

當 cwnd = 12 時改為執行擁塞避免演算法,擁塞視窗按按線性規律增長,每經過一個往返時延就增加一個 MSS 的大小。


乘法減小 (multiplicative decrease)

  • “乘法減小“是指不論在慢開始階段還是擁塞避免階段,只要出現一次超時(即出現一次網路擁塞),就把慢開始門限值 ssthresh 設定為當前的擁塞視窗值乘以 0.5。
  • 當網路頻繁出現擁塞時,ssthresh 值就下降得很快,以大大減少注入到網路中的分組數。

加法增大 (additive increase)

“加法增大”是指執行擁塞避免演算法後,在收到對所有報文段的確認後(即經過一個往返時間),就把擁塞視窗 cwnd增加一個 MSS 大小,使擁塞視窗緩慢增大,以防止網路過早出現擁塞。


注意:

  1. “擁塞避免”並非指完全能夠避免了擁塞。利用以上的措施要完全避免網路擁塞還是不可能的。
  2. “擁塞避免”是說在擁塞避免階段把擁塞視窗控制為按線性規律增長,使網路比較不容易出現擁塞。

2、快重傳和快恢復

快重傳演算法

  • 快重傳演算法首先要求接收方每收到一個失序的報文段後就立即發出重複確認。這樣做可以讓傳送方及早知道有報文段沒有到達接收方。
  • 傳送方只要一連收到三個重複確認就應當立即重傳對方尚未收到的報文段。
  • 不難看出,快重傳並非取消重傳計時器,而是在某些情況下可更早地重傳丟失的報文段。

快恢復演算法

1)、當傳送端收到連續三個重複的確認時,就執行“乘法減小”演算法,把慢開始門限 ssthresh 減半。但接下去不執行慢開始演算法。
2)、由於傳送方現在認為網路很可能沒有發生擁塞,因此現在不執行慢開始演算法,即擁塞視窗 cwnd 現在不設定為 1,而是設定為慢開始門限 ssthresh 減半後的數值,然後開始執行擁塞避免演算法(“加法增大”),使擁塞視窗緩慢地線性增大。

傳送視窗的上限值

傳送方的傳送視窗的上限值應當取為接收方視窗 rwnd 和擁塞視窗 cwnd 這兩個變數中較小的一個,即應按以下公式確定:
傳送視窗的上限值:\(傳送視窗的上限值 = Min[rwnd, cwnd]\)

  1. 當 rwnd < cwnd 時,是接收方的接收能力限制傳送視窗的最大值。
  2. 當 cwnd < rwnd 時,則是網路的擁塞限制傳送視窗的最大值。

5.8、TCP 傳輸連線管理

建議看這一篇轉載的文章https://blog.csdn.net/qq_43591881/article/details/107768812

運輸連線就有三個階段,即:連線建立資料傳送連線釋放。運輸連線的管理就是使運輸連線的建立和釋放都能正常地進行。

連線建立過程中要解決以下三個問題:

  • 要使每一方能夠確知對方的存在。
  • 要允許雙方協商一些引數(如最大報文段長度,最大視窗大小,服務質量等)。
  • 能夠對運輸實體資源(如快取大小,連線表中的專案等)進行分配。

5.8.1、TCP 連線建立——三次握手

  • TCP 連線的建立都是採用客戶伺服器方式。
  • 主動發起連線建立的應用程序叫做客戶(client)。
  • 被動等待連線建立的應用程序叫做伺服器(server)。
第一次握手

  • A 的 TCP 向 B 發出連線請求報文段,其首部中的同步位 SYN = 1,並選擇序號 seq = x,表明傳送資料時的第一個資料位元組的序號是 x。
第二次握手 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20200803173136455.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzNTkxODgx,size_16,color_FFFFFF,t_70)
  • B 的 TCP 收到連線請求報文段後,如同意,則發回確認。
  • B 在確認報文段中應使 SYN = 1,使 ACK = 1, 其確認號ack = x + 1,自己選擇的序號 seq = y。
第三次握手

  • A 收到此報文段後向 B 給出確認,其 ACK = 1,確認號 ack = y + 1。
  • A 的 TCP 通知上層應用程序,連線已經建立。
  • B 的 TCP 收到主機 A 的確認後,也通知其上層應用程序:TCP 連線已經建立。

確認雙方可傳送並且可接受,最少需要 3 次通訊。

前兩個資料包無法證明客戶端的接受能力時正常的。

抓包時相對序列號是從 0 開始的,但是真實的序列號不是從 0 開始的。

必須得有第三次握手,才能讓伺服器知道客戶端的狀態也是建立好的狀態。

就跟打電話一樣
A:“你聽到了嗎?”
B:“我聽到了”
A:“那就好”

Q:TCP 傳輸連線的建立為什麼要經過三次握手,而不是兩次握手,也就是第三次握手存在的意義是什麼?

A:下面假設了一種情景

1、客戶端 A 給伺服器 B 傳送一個建立會話的同步請求,但這個請求可能會走比較遠的路由,到達的時間可能會比較長一點,經過了比一個 RTT 時間多一點後,客戶端發現還沒有收到迴應,這時客戶端 A 再給伺服器 B 傳送一個請求,這次伺服器立刻就收到了,給了客戶端 A 一個迴應,前兩次請求足夠讓客戶端 A 和伺服器 B 協商一些引數。

2、這時如果伺服器 B 又收到了那個經過比較遠的路由傳送的同步請求,伺服器 B 呢,又會給客戶端 A 傳送一個確認,但此時客戶端 A 已經和伺服器 B 建立會話了,所以客戶端 A 它不會搭理伺服器 B 這一次的確認,而伺服器 B 會一直在等客戶端 A 的確認,就會造成伺服器資源的浪費。

3、如果沒有第三次確認,伺服器 B 就不知道客戶端 A 是否已經收到了我的確認,會話是否已經建立了。

5.8.2、三次握手建立 TCP 連線的各狀態

狀態 含義
LISTEN 表示 socket 已經處於 listen 狀態了,可以建立連線;
SYN-SENT 表示 socket 在發出 connect 連線的時候,會首先發送SYN報文,然後等待另一端傳送的確認報文 (ACK),表示這端已經發送完 SYN 報文了;
SYN-RCVD 表示一端已經接收到 SYN 報文了;
ESTAB-LISHED 表示已經建立連線了,可以傳送資料了。
CLOSED 這個狀態表示連線已經斷開。

Q:如何在客戶端檢視會話的 SYN-SENT 狀態呢?

A:訪問一個不存在的地址,會話請求發出去了,但該地址不存在伺服器,伺服器也就沒有傳送確認了,此時客戶端會話的狀態即為:SYN-SENT

提前開啟命令提示符提前輸入:netstat -n

例如訪問:http://192.168.2.200/

介紹一下 SYN 攻擊器

SYN 攻擊器是通過 TCP 建立連線的特點,也就是客戶端向伺服器傳送建立連線的請求,對於傳送方來說,這個請求裡可以偽造源 IP 地址。伺服器要給客戶端一個確認,對於接收方來說,目標 IP 地址是偽造,也就無法獲得客戶端的確認,從而伺服器會話狀態一直處於接收狀態,即 SYN-RCVD

從而一直浪費伺服器資源,攻擊次數和強度足夠大時,導致宕機。

Q:如何在服務端檢視會話的 SYN-RCVD狀態呢?

A:操作都要在虛擬機器中進行,通過一臺電腦使用 SYN 攻擊器攻擊另一臺伺服器,來檢視伺服器會話狀態。

5.8.3、TCP 連線釋放——四次揮手

第一次揮手

  • 資料傳輸結束後,通訊的雙方都可釋放連線。
  • 現在 A 的應用程序先向其 TCP 發出連線釋放報文段,並停止再發送資料,主動關閉 TCP 連線。
  • A 把連線釋放報文段首部的 FIN = 1,其序號 seq = u,等待 B 的確認。
第二次揮手

  • B 發出確認,確認號 ack = u + 1,而這個報文段自己的序號 seq = v。
    TCP 伺服器程序通知高層應用程序,A 通向 B 方向的連線已經釋放。
  • 從 A 到 B 這個方向的連線就釋放了,TCP 連線處於半關閉狀態。B 若傳送資料,A 仍要接收。
第三次揮手

  • 若 B 已經沒有要向 A 傳送的資料,其應用程序就通知 TCP 釋放連線。
第四次揮手

  • A 收到連線釋放報文段後,必須發出確認。
還是跟打電話一樣
A:“我說完了”
B:“收到”
B:“我也說完了”
A:“收到”

5.8.4、四次揮手釋放 TCP 連線的各狀態

狀態 含義
ESTAB-LISHED 這個狀態表示連線已經建立。
FIN-WAIT-1 表示在等待另一方的 FIN 報文,和 FIN_WAIT_2 的區別是,FIN_WAIT_1 表示 socket 現在要主動關閉連線,在傳送完 FIN 報文後 socket 進入 FIN_WAIT_1 狀態,當收到另一方傳送 FIN 的 ACK 之後立即進入 FIN_WAIT_2 狀態;
FIN-WAIT-2 同上,此時需要做的事情是可能還會接收資料,然後等待另一方的 FIN;也就是說此時傳送的通路已斷,接收的通路還是正常的。
TIME-WAIT 存在主動關閉的一方,表示收到了對方的 FIN 報文,併發送出了 ACK 報文,就等 2MSL(Max Segment Lifetime) 後即可回到 CLOSED 可用狀態了,需要等一段時間時原因是網路是不可靠的,不能保證這個 ACK 傳送成功了,如果失敗了,對端會超時重傳 FIN;
CLOSING 表示在傳送 FIN 之後,沒有收到對方的 ACK,而是收到了對方的 FIN,這中情況很少見,只有在兩端幾乎同時關閉同一個socket 的時候才會出現 CLOSING 狀態;
CLOSE-WAIT 表示收到對方的 FIN 之後,回給對方 ACK,此時處於CLOSE_WAIT 狀態,等待關閉,要看自己是否還有資料要傳送;
LAST-ACK 表示收到對方的 FIN 之後,回給對方 ACK,然後自己也要關閉傳送 FIN ,等待另一方的 ACK 時候的狀態;
CLOSED 這個狀態表示連線已經斷開。

注:TCP 連線必須經過時間 2MSL 後才真正釋放掉。

MSL(Maximum Segment Lifetime): 報文最大生存時間,報文最長壽命
Windows: MSL = 2min
linux(Ubuntu, CentOs): MSL = 60s
Unix: MSL = 30s

Q:為什麼第四次揮手後客戶端還要等待 2MSL 的時間,而不立刻 CLOSED呢?

A:

如果沒有 2MSL 的等待時間的話,客戶端立刻 CLOSED,一旦客戶端傳送的確認包丟失,而伺服器未收到確認,會一直髮送請求釋放連線的資料包,而這時客戶端已經關閉會話了,使得伺服器這端的會話一直處於 LAST-ACK 狀態,從而就無法關閉這次會話。

如果有 2MSL 的等待時間的話,如果客戶端發的確認包丟失了,在這 2MSL 的時間內,伺服器向我再次傳送請求釋放連線的資料包,我就能再次傳送確認。