通過本文,你可以優雅 get 到 TCP-IP 協議精華!

前言

大家好,這裏是浩道 Linux,主要給大家分享 Linux、Python、網絡通信、網絡安全等相關的 IT 知識平臺。

今天浩道跟大家分享關於 TCP/IP 協議的硬核乾貨,通過本文,相信你可以很優雅就可以學習到其精華!

本文整理了一些 TCP/IP 協議簇中需要必知必會的十大問題,既是面試高頻問題,又是 IT 工程人員必備基礎素養。

TCP/IP 十個問題

一、TCP/IP 模型

TCP/IP 協議模型(Transmission Control Protocol/Internet Protocol),包含了一系列構成互聯網基礎的網絡協議,是 Internet 的核心協議。

基於 TCP/IP 的參考模型將協議分成四個層次,它們分別是鏈路層、網絡層、傳輸層和應用層。下圖表示 TCP/IP 模型與 OSI 模型各層的對照關係。

TCP/IP 協議族按照層次由上到下,層層包裝。最上面的是應用層,這裏面有 http,ftp, 等等我們熟悉的協議。而第二層則是傳輸層,著名的 TCP 和 UDP 協議就在這個層次。第三層是網絡層,IP 協議就在這裏,它負責對數據加上 IP 地址和其他的數據以確定傳輸的目標。第四層是數據鏈路層,這個層次爲待傳送的數據加入一個以太網協議頭,並進行 CRC 編碼,爲最後的數據傳輸做準備。

上圖清楚地表示了 TCP/IP 協議中每個層的作用,而 TCP/IP 協議通信的過程其實就對應着數據入棧與出棧的過程。入棧的過程,數據發送方每層不斷地封裝首部與尾部,添加一些傳輸的信息,確保能傳輸到目的地。出棧的過程,數據接收方每層不斷地拆除首部與尾部,得到最終傳輸的數據。

上圖以 HTTP 協議爲例,具體說明。

二、數據鏈路層

物理層負責 0、1 比特流與物理設備電壓高低、光的閃滅之間的互換。
數據鏈路層負責將 0、1 序列劃分爲數據幀從一個節點傳輸到臨近的另一個節點, 這些節點是通過 MAC 來唯一標識的 (MAC, 物理地址,一個主機會有一個 MAC 地址)。

三、網絡層

1.IP 協議

IP 協議是 TCP/IP 協議的核心,所有的 TCP,UDP,IMCP,IGMP 的數據都以 IP 數據格式傳輸。要注意的是,IP 不是可靠的協議,這是說,IP 協議沒有提供一種數據未傳達以後的處理機制,這被認爲是上層協議:TCP 或 UDP 要做的事情。

1.1 IP 地址

在數據鏈路層中我們一般通過 MAC 地址來識別不同的節點,而在 IP 層我們也要有一個類似的地址標識,這就是 IP 地址。

32 位 IP 地址分爲網絡位和地址位,這樣做可以減少路由器中路由表記錄的數目,有了網絡地址,就可以限定擁有相同網絡地址的終端都在同一個範圍內,那麼路由表只需要維護一條這個網絡地址的方向,就可以找到相應的這些終端了。

A類IP地址: 0.0.0.0~127.0.0.0  
B類IP地址:128.0.0.1~191.255.0.0  
C類IP地址:192.168.0.0~239.255.255.0
1.2 IP 協議頭

這裏只介紹: 八位的 TTL 字段。這個字段規定該數據包在穿過多少個路由之後纔會被拋棄。某個 IP 數據包每穿過一個路由器,該數據包的 TTL 數值就會減少 1,當該數據包的 TTL 成爲零,它就會被自動拋棄。 

這個字段的最大值也就是 255,也就是說一個協議包也就在路由器裏面穿行 255 次就會被拋棄了,根據系統的不同,這個數字也不一樣,一般是 32 或者是 64。

2.ARP 及 RARP 協議

ARP 是根據 IP 地址獲取 MAC 地址的一種協議。

ARP(地址解析)協議是一種解析協議,本來主機是完全不知道這個 IP 對應的是哪個主機的哪個接口,當主機要發送一個 IP 包的時候,會首先查一下自己的 ARP 高速緩存(就是一個 IP-
MAC 地址對應表緩存)。

如果查詢的 IP-MAC 值對不存在,那麼主機就向網絡發送一個 ARP 協議廣播包,這個廣播包裏面就有待查詢的 IP 地址,而直接收到這份廣播的包的所有主機都會查詢自己的 IP 地址,如果收到廣播包的某一個主機發現自己符合條件,那麼就準備好一個包含自己的 MAC 地址的 ARP 包傳送給發送 ARP 廣播的主機。

而廣播主機拿到 ARP 包後會更新自己的 ARP 緩存(就是存放 IP-
MAC 對應表的地方)。發送廣播的主機就會用新的 ARP 緩存數據準備好數據鏈路層的的數據包發送工作。

RARP 協議的工作與此相反,不做贅述。

3. ICMP 協議

IP 協議並不是一個可靠的協議,它不保證數據被送達,那麼,自然的,保證數據送達的工作應該由其他的模塊來完成。其中一個重要的模塊就是 ICMP(網絡控制報文) 協議。ICMP 不是高層協議,而是 IP 層的協議。

當傳送 IP 數據包發生錯誤。比如主機不可達,路由不可達等等,ICMP 協議將會把錯誤信息封包,然後傳送回給主機。給主機一個處理錯誤的機會,這
也就是爲什麼說建立在 IP 層以上的協議是可能做到安全的原因。

四、ping

ping 可以說是 ICMP 的最著名的應用,是 TCP/IP 協議的一部分。利用 “ping” 命令可以檢查網絡是否連通,可以很好地幫助我們分析和判定網絡故障。

例如:當我們某一個網站上不去的時候。通常會 ping 一下這個網站。ping 會回顯出一些有用的信息。一般的信息如下:

ping 這個單詞源自聲納定位,而這個程序的作用也確實如此,它利用 ICMP 協議包來偵測另一個主機是否可達。原理是用類型碼爲 0 的 ICMP 發請

求,受到請求的主機則用類型碼爲 8 的 ICMP 迴應。

ping 程序來計算間隔時間,並計算有多少個包被送達。用戶就可以判斷網絡大致的情況。我們可以看到, ping 給出來了傳送的時間和 TTL 的數據。

五、Traceroute

Traceroute 是用來偵測主機到目的主機之間所經路由情況的重要工具,也是最便利的工具。

Traceroute 的原理是非常非常的有意思,它收到到目的主機的 IP 後,首先給目的主機發送一個 TTL=1 的 UDP 數據包,而經過的第一個路由器收到這個數據包以後,就自動把 TTL 減 1,而 TTL 變爲 0 以後,路由器就把這個包給拋棄了,並同時產生
一個主機不可達的 ICMP 數據報給主機。主機收到這個數據報以後再發一個 TTL=2 的 UDP 數據報給目的主機,然後刺激第二個路由器給主機發 ICMP 數據報。如此往復直到到達目的主機。這樣,traceroute 就拿到了所有的路由器 IP。

六、TCP/UDP

TCP/UDP 都是是傳輸層協議,但是兩者具有不同的特性,同時也具有不同的應用場景,下面以圖表的形式對比分析。

面向報文

面向報文的傳輸方式是應用層交給 UDP 多長的報文,UDP 就照樣發送,即一次發送一個報文。因此,應用程序必須選擇合適大小的報文。若報文太長,則 IP 層需要分片,降低效率。若太短,會是 IP 太小。

面向字節流

面向字節流的話,雖然應用程序和 TCP 的交互是一次一個數據塊(大小不等),但 TCP 把應用程序看成是一連串的無結構的字節流。TCP 有一個緩衝,當應用程序傳送的數據塊太長,TCP 就可以把它劃分短一些再傳送。

關於擁塞控制,流量控制,是 TCP 的重點,後面講解。

TCP 和 UDP 協議的一些應用

什麼時候應該使用 TCP?

當對網絡通訊質量有要求的時候,比如:整個數據要準確無誤的傳遞給對方,這往往用於一些要求可靠的應用,比如 HTTP、HTTPS、FTP 等傳輸文件的協議,POP、SMTP 等郵件傳輸的協議。

什麼時候應該使用 UDP?

當對網絡通訊質量要求不高的時候,要求網絡通訊速度能儘量的快,這時就可以使用 UDP。

七、DNS

DNS(Domain Name
System,域名系統),因特網上作爲域名和 IP 地址相互映射的一個分佈式數據庫,能夠使用戶更方便的訪問互聯網,而不用去記住能夠被機器直接讀取的 IP 數串。通過主機名,最終得到該主機名對應的 IP 地址的過程叫做域名解析(或主機名解析)。DNS 協議運行在 UDP 協議之上,使用端口號 53。

八、TCP 連接的建立與終止

1. 三次握手

TCP 是面向連接的,無論哪一方向另一方發送數據之前,都必須先在雙方之間建立一條連接。在 TCP/IP 協議中,TCP 協議提供可靠的連接服務,連接是通過三次握手進行初始化的。三次握手的目的是同步連接雙方的序列號和確認號並交換
TCP 窗口大小信息。

第一次握手: 建立連接。客戶端發送連接請求報文段,將 SYN 位置爲 1,Sequence
Number 爲 x;然後,客戶端進入 SYN_SEND 狀態,等待服務器的確認;

第二次握手: 服務器收到 SYN 報文段。服務器收到客戶端的 SYN 報文段,需要對這個 SYN 報文段進行確認,設置 Acknowledgment Number 爲 x+1(Sequence Number+1);同時,自己自己還要發送 SYN 請求信息,將 SYN 位置爲 1,Sequence
Number 爲 y;服務器端將上述所有信息放到一個報文段(即 SYN+ACK 報文段)中,一併發送給客戶端,此時服務器進入 SYN_RECV 狀態;

第三次握手: 客戶端收到服務器的 SYN+ACK 報文段。然後將 Acknowledgment
Number 設置爲 y+1,向服務器發送 ACK 報文段,這個報文段發送完畢以後,客戶端和服務器端都進入 ESTABLISHED 狀態,完成 TCP 三次握手。

爲什麼要三次握手?

爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤。

具體例子:“已失效的連接請求報文段”的產生在這樣一種情況下:client 發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達 server。本來這是一個早已失效的報文段。但 server 收到此失效的連接請求報文段後,就誤認爲是 client 再次發出的一個新的連接請求。於是就向 client 發出確認報文段,同意建立連接。假設不採用 “三次握手”,那麼只要 server 發出確認,新的連接就建立了。由於現在 client 並沒有發出建立連接的請求,因此不會理睬 server 的確認,也不會向 server 發送數據。但 server 卻以爲新的運輸連接已經建立,並一直等待 client 發來數據。這樣,server 的很多資源就白白浪費掉了。採用“三次握手” 的辦法可以防止上述現象發生。例如剛纔那種情況,client 不會向 server 的確認發出確認。server 由於收不到確認,就知道 client 並沒有要求建立連接。”

2. 四次揮手

當客戶端和服務器通過三次握手建立了 TCP 連接以後,當數據傳送完畢,肯定是要斷開 TCP 連接的啊。那對於 TCP 的斷開連接,這裏就有了神祕的 “四次分手”。

第一次分手: 主機 1(可以是客戶端,也可以是服務器端),設置 Sequence
Number,向主機 2 發送一個 FIN 報文段;此時,主機 1 進入 FIN_WAIT_1 狀態;這表示主機 1 沒有數據要發送給主機 2 了;

第二次分手: 主機 2 收到了主機 1 發送的 FIN 報文段,向主機 1 回一個 ACK 報文段,Acknowledgment Number 爲 Sequence Number 加 1;主機 1 進入 FIN_WAIT_2 狀態;主機 2 告訴主機 1,我 “同意” 你的關閉請求;

第三次分手: 主機 2 向主機 1 發送 FIN 報文段,請求關閉連接,同時主機 2 進入 LAST_ACK 狀態;

第四次分手: 主機 1 收到主機 2 發送的 FIN 報文段,向主機 2 發送 ACK 報文段,然後主機 1 進入 TIME_WAIT 狀態;主機 2 收到主機 1 的 ACK 報文段以後,就關閉連接;此時,主機 1 等待 2MSL 後依然沒有收到回覆,則證明 Server 端已正常關閉,那好,主機 1 也可以關閉連接了。

爲什麼要四次分手?

TCP 協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。TCP 是全雙工模式,這就意味着,當主機 1 發出 FIN 報文段時,只是表示主機 1 已經沒有數據要發送了,主機 1 告訴主機 2,它的數據已經全部發送完畢了;但是,這個時候主機 1 還是可以接受來自主機 2 的數據;當主機 2 返回 ACK 報文段時,表示它已經知道主機 1 沒有數據發送了,但是主機 2 還是可以發送數據到主機 1 的;當主機 2 也發送了 FIN 報文段時,這個時候就表示主機 2 也沒有數據要發送了,就會告訴主機 1,我也沒有數據要發送了,之後彼此就會愉快的中斷這次 TCP 連接。

爲什麼要等待 2MSL?

MSL:報文段最大生存時間,它是任何報文段被丟棄前在網絡內的最長時間。 
原因有二:

第一點:如果主機 1 直接 CLOSED 了,那麼由於 IP 協議的不可靠性或者是其它網絡原因,導致主機 2 沒有收到主機 1 最後回覆的 ACK。那麼主機 2 就會在超時之後繼續發送 FIN,此時由於主機 1 已經 CLOSED 了,就找不到與重發的 FIN 對應的連接。所以,主機 1 不是直接進入 CLOSED,而是要保持 TIME_WAIT,當再次收到 FIN 的時候,能夠保證對方收到 ACK,最後正確的關閉連接。

第二點:如果主機 1 直接 CLOSED,然後又再向主機 2 發起一個新連接,我們不能保證這個新連接與剛關閉的連接的端口號是不同的。也就是說有可能新連接和老連接的端口號是相同的。一般來說不會發生什麼問題,但是還是有特殊情況出現:假設新連接和已經關閉的老連接端口號是一樣的,如果前一次連接的某些數據仍然滯留在網絡中,這些延遲數據在建立新連接之後纔到達主機 2,由於新連接和老連接的端口號是一樣的,TCP 協議就認爲那個延遲的數據是屬於新連接的,這樣就和真正的新連接的數據包發生混淆了。所以 TCP 連接還要在 TIME_WAIT 狀態等待 2 倍 MSL,這樣可以保證本次連接的所有數據都從網絡中消失。

九、TCP 流量控制

如果發送方把數據發送得過快,接收方可能會來不及接收,這就會造成數據的丟失。所謂 流量控制 就是讓發送方的發送速率不要太快,要讓接收方來得及接收。

利用 滑動窗口機制 可以很方便地在 TCP 連接上實現對發送方的流量控制。

設 A 向 B 發送數據。在連接建立時,B 告訴了 A:“我的接收窗口是 rwnd = 400”(這裏的 rwnd 表示 receiver window)
。因此,發送方的發送窗口不能超過接收方給出的接收窗口的數值。請注意,TCP 的窗口單位是字節,不是報文段。假設每一個報文段爲 100 字節長,而數據報文段序號的初始值設爲 1。大寫 ACK 表示首部中的確認位 ACK,小寫 ack 表示確認字段的值 ack。

從圖中可以看出,B 進行了三次流量控制。第一次把窗口減少到 rwnd = 300 ,第二次又減到了 rwnd = 100 ,最後減到 rwnd = 0,即不允許發送方再發送數據了。這種使發送方暫停發送的狀態將持續到主機 B 重新發出一個新的窗口值爲止。B 向 A 發送的三個報文段都設置了 ACK = 1,只有在 ACK=1 時確認號字段纔有意義。

TCP 爲每一個連接設有一個持續計時器 (persistence timer)。只要 TCP 連接的一方收到對方的零窗口通知,就啓動持續計時器。若持續計時器設置的時間到期,就發送一個零窗口控測報文段(攜 1 字節的數據),那麼收到這個報文段的一方就重新設置持續計時器。

十、TCP 擁塞控制

1. 慢開始和擁塞避免

發送方維持一個擁塞窗口 cwnd ( congestion window
) 的狀態變量。擁塞窗口的大小取決於網絡的擁塞程度,並且動態地在變化。發送方讓自己的發送窗口等於擁塞窗口。

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

慢開始算法:

當主機開始發送數據時,如果立即所大量數據字節注入到網絡,那麼就有可能引起網絡擁塞,因爲現在並不清楚網絡的負荷情況。 
因此,較好的方法是 先探測一下,即由小到大逐漸增大發送窗口,也就是說,由小到大逐漸增大擁塞窗口數值。

通常在剛剛開始發送報文段時,先把擁塞窗口 cwnd
設置爲一個最大報文段 MSS 的數值。而在每收到一個對新的報文段的確認後,把擁塞窗口增加至多一個 MSS 的數值。用這樣的方法逐步增大發送方的擁塞窗口 cwnd
,可以使分組注入到網絡的速率更加合理。

每經過一個傳輸輪次,擁塞窗口 cwnd 就加倍。一個傳輸輪次所經歷的時間其實就是往返時間 RTT。

不過 “傳輸輪次” 更加強調:把擁塞窗口 cwnd 所允許發送的報文段都連續發送出去,並收到了對已發送的最後一個字節的確認。

另,慢開始的 “慢” 並不是指 cwnd 的增長速率慢,而是指在 TCP 開始發送報文段時先設置 cwnd=1,使得發送方在開始時只發送一個報文段(目的是試探一下網絡的擁塞情況),然後再逐漸增大 cwnd。

爲了防止擁塞窗口 cwnd 增長過大引起網絡擁塞,還需要設置一個慢開始門限 ssthresh 狀態變量。慢開始門限 ssthresh 的用法如下:

擁塞避免

讓擁塞窗口 cwnd 緩慢地增大,即每經過 一個往返時間 RTT 就把發送方的 擁塞窗口 cwnd 加 1,而不是加倍
。這樣擁塞窗口 cwnd 按線性規律緩慢增長,比慢開始算法的擁塞窗口增長速率緩慢得多。

無論在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(其根據就是沒有收到確認),就要把慢開始門限 ssthresh 設置爲出現擁塞時的發送
方窗口值的一半(但不能小於 2)。然後把擁塞窗口 cwnd 重新設置爲 1,執行慢開始算法。

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

如下圖,用具體數值說明了上述擁塞控制的過程。現在發送窗口的大小和擁塞窗口一樣大。

2. 快重傳和快恢復

快重傳

快重傳算法首先要求接收方每收到一個失序的報文段後就立即發出重複確認(爲的是使發送方及早知道有報文段沒有到達對方)而不要等到自己發送數據時才進行捎帶確認。

接收方收到了 M1 和 M2 後都分別發出了確認。現在假定接收方沒有收到 M3 但接着收到了 M4。

顯然,接收方不能確認 M4,因爲 M4 是收到的失序報文段。根據 可靠傳輸原理,接收方可以什麼都不做,也可以在適當時機發送一次對 M2 的確認。

但按照快重傳算法的規定,接收方應及時發送對 M2 的重複確認,這樣做可以讓
發送方及早知道報文段 M3 沒有到達接收方。發送方接着發送了 M5 和 M6。接收方收到這兩個報文後,也還要再次發出對 M2 的重複確認。這樣,發送方共收到了
接收方的四個對 M2 的確認,其中後三個都是重複確認。

快重傳算法還規定,發送方只要一連收到三個重複確認就應當立即重傳對方尚未收到的報文段 M3,而不必 繼續等待 M3 設置的重傳計時器到期。

由於發送方儘早重傳未被確認的報文段,因此採用快重傳後可以使整個網絡吞吐量提高約 20%。

快恢復

與快重傳配合使用的還有快恢復算法,其過程有以下兩個要點:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-gnPI79iI8PzcroYvPWwkA