計算機網絡是面試中的重點,尤其是一些高頻題目,比如TCP、UDP協議以及TCP的三次握手四次揮手還有關於TCP的一系列知識,這篇文章就是自己總結的傳輸層的重點知識,適合面試前複習鞏固。
傳輸層
一、總覽整個傳輸層的重點
圖太大了,只能壓縮,就會有些模糊。不過圖只是給一個總覽,接下來我們會一一介紹這些知識滴。
二、傳輸層基本知識
1. 多路複用和多路分用
多路分用:在接收端將傳輸層的報文段交給正確的套接字工作就是多路分用
多路複用:在發送端將不同的套接字中收集到的數據塊封裝上首部信息後發送出去就叫多路複用
多路複用和多路分用是傳輸層要做的最基礎的事情,通過多路複用和分用就可以將網絡層的信息交到對應的應用層,也可以將應用層協議發送到網絡層。
TCP和UDP協議都實現了多路複用和分用。
2.多路分用工作
主機接受到網絡層傳送來的IP數據報後,在首部中解析到源端口號、目的端口號等信息,然後將數據報交給應用層對應的Socket
其中UDP無連接服務是使用目的IP、目的端口號來標識。這樣來自不同IP地址不同端口的數據包都會導入到同一個Socket
而TCP是使用源IP、目的IP、源端口、目的端口來標識。只有四個都相同時,纔會導向同一個Socket,Web服務器爲每一個客戶端開不同的Socket
三、UDP協議
1. UDP基本特點
- 基於IP協議提供了:
複用和分用、最簡單的錯誤校驗 - "Best effort"服務:
盡力而爲,UDP段不保證數據傳輸的可靠性,數據包可能會丟失或未按序到達 - 無連接
不需要進行握手、每個UDP段的處理獨立於其它段,也不會維護連接的狀態
2.UDP爲什麼存在?
- 無需建立連接 —— 減少延遲
- 實現簡單 —— 無需維護連接狀態
- 頭部開銷少—— TCP 20字節,UDP 8字節
- 沒有擁塞控制 —— 應用層可更好的控制發送時間和速率
3.UDP的應用
- 用於流媒體應用 —— 容忍丟失、速率敏感
- 用於DNS協議 —— 使用UDP傳輸速度更快
- 用於RIP路由選擇表的更新 —— 路由表更新迭代快
4.UDP首部格式
UDP首部包含:
- 源端口號:表示數據是從哪個進程來
- 目的端口號:表示數據是從要到哪個進程去
- 16位UDP長度:表示整個數據報(UDP首部+UDP數據)的最大長度
- 校驗和:如果校驗和出錯, 就會直接丟棄
四、TCP協議
1.TCP概述
- 點對點:一個發送方,一個接收方
- 可靠的、按序的字節流
- 流水線機制:TCP有擁塞控制和流量控制
- 發送方接收方緩存
- 全雙工:同一個連接中能夠傳輸雙向數據流
- 面向連接:
(1)通信雙方在發送數據之前必須建立連接
(2)連接狀態只在連接的兩端中維護,在沿途的節點中並不維護 - TCP連接包括:兩臺主機上的緩存、連接狀態變量、socket等
2. TCP報文段的結構
- 源/目的端口號: 表示數據是從哪個進程來, 到哪個進程去
- 32位序號:表示這個報文段數據的第一個開始字節的編號
- 32位確認號: 表示希望下一次收到的字節的序列號
- 4位TCP報頭長度: 表示該TCP頭部有多少個32位bit(有多少個4字節)
- 6位標誌位:
URG: 緊急指針是否有效
ACK: 確認號是否有效
PSH: 提示接收端應用程序立刻從TCP緩衝區把數據讀走
RST: 對方要求重新建立連接; 我們把攜帶RST標識的稱爲復位報文段
SYN: 請求建立連接; 我們把攜帶SYN標識的稱爲同步報文段
FIN: 通知對方, 本端要關閉了, 我們稱攜帶FIN標識的爲結束報文段 - 16位窗口大小: 接收窗口的大小,用在流量管理中
- 16位校驗和: 如果校驗和出錯, 就會直接丟棄.
- 16位緊急指針: 標識哪部分數據是緊急數據;
這裏的序列號是指每一個被分開的數據報中的第一個字節的標號而不是整個數據報的編號
確認序號表示的是希望接收的下一個字節的序列號,也表示在這個序列號之前的所以字節都以及被成功接收。
5.連接控制
(1)三次握手
三次握手流程:
- 首先客戶端未開始發起連接時處於 CLOSE 狀態,服務器處於LISTEN 狀態。客戶端發器鏈接時,首先發送一個不含有數據的特殊報文段,被稱爲SYN報文段。這個報文段中,首部標誌位SYN置1表示請求建立連接,並且在首部的序列號中生成自己的傳輸數據的起始序列號:client_isn,一併發送到服務端。發送後,客戶端狀態變爲 SYN_SENT
- 當服務器收到客戶端的建立連接的請求時,就開始爲此次連接創建緩存和變量。同時,服務端要向客戶端發送請求連接以及確認應答的報文段,稱之爲SYNACK報文段。在這個報文段中,首部標誌位SYN置1表示請求連接,並且服務端生成自己的發送數據起始序列號:sever_isn,同時要對客戶端發來的SYN報文段進行確認,也就是將自己的ACK確認號設置爲client_isn + 1,一併發回客戶端。發送後,服務端狀態變爲SYN_RCVD
- 客戶端收到SYNACK報文段後,也開始爲此次連接創建緩存和變量。同時客戶端要向服務端發送一個確認的ACK包。在這次的數據首部中,SYN就可以置0,ACK確認號就爲sever_isn+1,序列號爲client_isn + 1。同時第三次握手時可以攜帶數據。發送出後,客戶端狀態變爲ESTABLISHED ,表示已經建立連接,服務端收到ACK包後,狀態也變爲ESTABLISHED 。至此,三次握手結束,兩端正式建立連接。
(2)四次揮手
四次揮手流程:
- 客戶端發起連接結束,發送一個FIN報文段,這個報文段首部的FIN標誌位置1表示要斷開連接。發送後,客戶端狀態變爲FIN_WAIT1 狀態
- 服務端接收到這個報文段後,得知客戶端想斷開連接,首先發送一個ACK報文段表示收到這個請求,發送後服務端狀態變爲CLOSE_WAIT狀態,此時服務端不會立馬斷開連接,而是等待將所有未傳輸完的報文都傳輸給客戶端後,再準備斷開連接。客戶端接收到這個ACK報文段後,狀態變爲FIN_WAIT2
- 當服務端準備好斷開連接時,會主動發送一個FIN報文段給客戶端,表示已經可以斷開連接了。發送這個報文段後,服務端的狀態就變爲LAST_ACK
- 客戶端收到這個FIN報文段後,就會回發一個ACK包給服務端,表示已經收到了,此時服務端收到後就關閉了連接,而客戶端進入TIME_WAIT,這個階段客戶端會等待一段時間後才關閉連接,以確保服務端確實收到了ACK包,否則如果ACK丟失就會進行重傳。至此四次揮手結束,客戶端服務端正式斷開連接。
常見問題:
📌爲什麼要進行三次握手,兩次可以嗎?四次呢?
答:兩次握手不可以,四次握手沒必要
三次握手可以使客戶端和服務端都得到 自身和對方的發送接收數據報的能力使正常的:
- 第一次握手後,服務端得知客戶端的發送能力和自己的接收能力是正常的
- 第二次握手後,客戶端得知自己的發送能力接收能力以及服務端的發送能力接收能力是正常的
- 第三次握手後,服務端得知客戶端的接收能力和自己發送能力是正常的
通過這三次的握手,使連接兩端都確定了發送接收能力的正常。顯然兩次還不夠,三次剛剛好,四次也沒有必要了。
另外一個原因就是,防止創建一些過期或者重複的連接。比如之前客戶端發送了第一次握手的SYN包,但由於網絡問題延時了,客戶端會重發一個包建立連接,成功建立連接後,之前的延時包到達了,此時服務端就會準備建立連接,如果只有兩次握手,那這個連接就被成功建立,而顯然連接建立後客戶端不會有進一步的操作了,這就會不斷創建空的連接。而使用三次握手,由於缺少第三次握手,服務端沒有等到最後的ACK包,導致連接沒有成功建立,也就避免上面的問題。
📌爲什麼要進行四次揮手?
在這之前,要明白——發送FIN不是表示立馬斷開連接,而是本端沒有繼續要發送的數據了
這樣再來看,客戶端發送FIN後,表示沒有需要發送的數據了,但它仍然使可以接收數據的。服務端接收到FIN也不會立即關閉,因爲這隻表示對端沒有數據要發了,而服務端的數據還沒發完。所以服務端先回應一個ACK後將自己所有的數據都發完後再次進行發送FIN表示服務端也沒有數據要發送了,但這個FIN必須要讓客戶端接收到,否則客戶端就會進行“傻等”。因此還需要客戶端發送最後一次的確認ACK包。所以,四次揮手一次都不可缺少!
📌爲什麼要有TIME_WAIT 狀態?
TIME_WAIT 狀態就是最後一次握手中,客戶端發送ACK後會等待一段時間保證對端成功接收到確認包。
如果沒有,試想一下當ACK並沒有到達服務端,服務端判斷超時後就會重複的發送FIN包。如果有一個相同地址的連接再次建立,就會莫名收到一個FIN結束連接的報文段,這就會造成很大的影響,所以必須要有這個狀態確保服務器收到了最後的ACK報文段。
4. 可靠傳輸的保證
我們已經知道了,TCP協議是一個可靠的傳輸協議。相比於UDP協議,它在應用層做了更多的工作,那麼TCP是怎樣保證可靠傳輸的呢?
(1)數據流編號
TCP協議是面向字節流傳輸的,它可以將上層傳來的所有數據流進行編號,然後對數據進行分包按序發送。而UDP只能直接發送所有的數據並不會進行分包分組發送。
(2) 確認重傳機制
首先想到需要解決的問題就是丟包和延時到達的問題,如果數據報在傳輸中丟失,那對於TCP協議就一定要在傳輸層做出反應,這個反應就是確認重傳。
怎麼知道丟包了呢?這就使用到了上面介紹了的TCP的首部結構中的有兩個數據分別是序列號和確認號。
在建立連接時,接收端和發送端都指定了自己開始發送字節流的序列號,每次接收端收到數據報後就會將收到的序列號+1作爲確認號ACK發送給發送端。這樣發送端接收到,就知道對端已經收到了自己的這個序列號的數據報。
所以,如果發生了丟包和延時,發送端就會收不到對端的ACK包,如果到達一定的時間,發送端就會重新再次發送未被確認的包,直到收到該序列號的ACK包後才繼續發送接下來的數據。因此TCP協議使用序列號和確認號,實現了發送端和接收端的“交流”保證了數據報可以安全的到達對端。
(3) 流量控制
我們都知道,TCP的發送端和接收端都有緩存。對於發送端而言,可以控制自己的發送速度,對於接收端而言只能無條件接受,但如果接收端的緩存區滿了而發送端還是不停的發送數據,就會造成數據報的丟失。所以TCP實現了流量控制,以便於發送端能感知接收端的剩餘緩存大小,來合適的調整發送速率。
這裏用到了TCP首部的數據:接收窗口。這個窗口就用來表示接收端剩餘可接收數據報的大小。每次接收端向發送端發送數據報時就會在首部的接收窗口位置加上自己緩衝區的剩餘大小。這樣發送端收到後就根據這個大小來控制發送。
如果接收窗口爲0表示已經沒有緩衝區了,需要讓發送端停止發送一段時間。此時爲了能實時獲取接收窗口的修改,發送端會每隔一段時間發送一個很小的數據包來試探,接收端就會再次發送自己的接收窗口大小,如果不爲零,發送端恢復發送。
(4)擁塞控制
很多人會將流量控制和擁塞控制搞混,其實,流量控制是對於接收端的接受能力而言,而擁塞控制是對於整個網絡而言,當整個網絡相對擁塞時,TCP協議也會做出反應,適當降低自己的發送數據包的數量。擁塞控制也有個相關數值就是擁塞窗口表示每次能發送的數據報的數量。發送端每次發送的數據包數量爲接受窗口和擁塞窗口的最小值。
整個擁塞控制有三個階段,分別是慢啓動、擁塞避免、快速恢復
階段一:慢啓動
在建立連接時,擁塞窗口的初始值爲1,也就是第一次只發送一個數據報,當收到這次發送的數據報應答後,擁塞窗口的大小變爲之前的兩倍就是2。相應的,如果成功接收到第二次的這兩個數據報,那擁塞窗口就調整爲4,以此類推。
那什麼時候會停下慢啓動呢?
- 超時沒收到ACK,表示丟包。此時將擁塞窗口值減爲1,再次進行慢啓動過程。這裏又有一個變量:慢啓動閾值,這個慢啓動閾值被設置爲上次達到擁塞後的擁塞窗口的一半。
- 當擁塞窗口當前的值達到或超過了慢啓動閾值,也就是達到了上次擁塞時擁塞窗口值得一半,此時在進行翻倍就有些“魯莽”,所以此時結束慢啓動,並進入擁塞避免模式。
- 收到3個冗餘的ACK,表示網絡已經有些擁堵,但也不至於直接減爲1,此時執行快速重傳並進入快速恢復模式。
快速重傳是在收到3個冗餘ACK後的反應,此時TCP認爲在這冗餘的ACK後的數據均已經丟失,於是就會在下一次超時之前就將丟失的報文段快速重傳到接收端。
階段二:擁塞避免
在擁塞避免這個階段,表示當前已經達到了慢啓動閾值,此時不進行繼續翻倍,而是線性增長,一次只+1,這樣可以保證更加的穩妥。
何時結束擁塞避免呢?
- 出現超時丟包時:與前面一樣,慢啓動閾值更新爲擁塞窗口的一半且擁塞窗口減爲1,重新進入慢啓動。
- 出現3個冗餘ACK:慢啓動閾值更新爲擁塞窗口的一半且擁塞窗口值減半,進入快速恢復狀態
階段三:快速恢復
在快速恢復狀態中,對於收到的每一個冗餘的ACK,擁塞窗口+1,最終當丟失的報文段的ACK到達後,TCP降低擁塞窗口值並進入擁塞避免狀態。當然如果出現超時丟包後,擁塞窗口還是減爲1進入慢啓動。
以上就是我認爲傳輸層需要掌握的重點知識的總結,也適合面試前的突擊複習,多多總結能讓整個知識體系更加清晰。如果有任何問題歡迎指正,也歡迎小夥伴們點贊關注一起進步。