TCP與UDP詳解

歡迎來我的個人網站,裏面有最新的版本

這篇介紹了下TCP與UDP面試題常考內容,並做了延伸,解釋了原理。

面試題

tcp和udp的區別

tcp如何實現可靠性

怎麼實現擁塞控制

cookie、session

一、TCP/IP協議

TCP/IP(Transmission Control Protocol/Internet Protocol,傳輸控制協議/網際協議)是指能夠在多個不同網絡間實現信息傳輸的協議簇。TCP/IP協議不僅僅指的是TCP 和IP兩個協議,而是指一個由FTP、SMTP、TCP、UDP、IP等協議構成的協議簇。TCP/IP 定義了電子設備如何連入因特網,以及數據如何在它們之間傳輸的標準。
我的理解: 互聯網中的設備要相互通信,必須基於相同的方式,比如由哪一方發起通訊,使用什麼語言進行通訊,怎麼結束通訊這些都要事先確定,不同設備之間的通訊都需要一種規則,我們將這種規則成爲協議。

1.1 TCP/IP 的分層管理圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-D4CvhZSt-1588931594515)(https://cdn.jsdelivr.net/gh/hhf443/blog-graph/img/20200508144146.png)]

1.1.1 應用層

TCP/IP模型將OSI參考模型中的會話層和表示層的功能合併到應用層實現。這一層主要的代表有DNS域名解析/http協議

1.1.2 傳輸層

在TCP/IP模型中,傳輸層的功能是使源端主機和目標端主機上的對等實體可以進行會話。在傳輸層定義了兩種服務質量不同的協議。即:傳輸控制協議TCP和用戶數據報協議UDP.

1.1.3 網絡層

網絡層是整個TCP/IP協議棧的核心。它的功能是把分組發往目標網絡或主機。同時,爲了儘快地發送分組,可能需要沿不同的路徑同時進行分組傳遞。因此,分組到達的順序和發送的順序可能不同,這就需要上層必須對分組進行排序。網絡層定義了分組格式和協議,即IP協議(Internet Protocol )。

1.1.4 物理層

該層負責 比特流在節點之間的傳輸,即負責物理傳輸,這一層的協議既與鏈路有關,也與傳輸的介質有關。通俗來說就是把計算機連接起來的物理手段。

1.1.5 數據鏈路層

控制網絡層與物理層之間的通信,主要功能是保證物理線路上進行可靠的數據傳遞。爲了保證傳輸,從網絡層接收到的數據被分割成特定的可被物理層傳輸的幀。幀是用來移動數據結構的結構包,他不僅包含原始數據,還包含發送方和接收方的物理地址以及糾錯和控制信息。其中的地址確定了幀將發送到何處,而糾錯和控制信息則確保幀無差錯到達。如果在傳達數據時,接收點檢測到所傳數據中有差錯,就要通知發送方重發這一幀。

二、UDP

2.1 首部

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-t1tM74Om-1588931594539)(https://cdn.jsdelivr.net/gh/hhf443/blog-graph/img/20200508150841.png)]

UDP用戶數據報有兩個字段:首部字段和數據字段,數據字段很簡單,只有8個字節;首部由四個字段組成,每個字段的長度都是兩個字節。各字段意義如下:

  1. 源端口: 源端口號,在需要給對方回信時使用。不需要是可全用0.
  2. 目的端口號: 這在終點交付報文時必須使用。
  3. 長度: 用戶數據報UDP的長度,最小爲8(僅首部)。
  4. 校驗和: 用於校驗用戶數據報在傳輸過程是否出錯,出錯則丟棄該報文

三、TCP

3.1 首部

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xfxGUGvx-1588931594546)(https://cdn.jsdelivr.net/gh/hhf443/blog-graph/img/20200508144900.png)]

源端口和目的端口: 各佔兩個字節,分別寫入源端口號和目的端口號。
序號 : 佔4個字節;用於對字節流進行編號,例如序號爲 301,表示第一個字節的編號爲 301,如果攜帶的數據長度爲 100 字節,那麼下一個報文段的序號應爲 401。
確認號 : 佔4個字節;期望收到的下一個報文段的序號。例如 B 正確收到 A 發送來的一個報文段,序號爲 501,攜帶的數據長度爲 200 字節,因此 B 期望下一個報文段的序號爲 701,B 發送給 A 的確認報文段中確認號就爲 701。
數據偏移 : 佔4位;指的是數據部分距離報文段起始處的偏移量實際上指的是首部的長度
確認 ACK : 當 ACK=1 時確認號字段有效,否則無效。TCP 規定,在連接建立後所有傳送的報文段都必須把 ACK 置 1。
同步 SYN :在連接建立時用來同步序號。當 SYN=1,ACK=0 時表示這是一個連接請求報文段。若對方同意建立連接,則響應報文中 SYN=1,ACK=1。
終止 FIN : 用來釋放一個連接,當 FIN=1 時,表示此報文段的發送方的數據已發送完畢,並要求釋放連接。
窗口 : 佔2字節;窗口值作爲接收方讓發送方設置其發送窗口的依據。之所以要有這個限制,是因爲接收方的數據緩存空間是有限的。
檢驗和: 佔2個字節;檢驗和字段檢驗的範圍包括首部和數據這兩個部分。在計算檢驗和時,在TCP報文段的前面加上12字節的僞首部。

緊急指針字段:佔 16 位,指出在本報文段中緊急數據共有多少個字節(緊急數據放在本報文段數據的最前面);

套接字: TCP連接的端點叫做套接字或插口。端口號拼接到IP地址即構成了套接字。

3.2 三次握手

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-K9j5Tf1r-1588931594553)(https://cdn.jsdelivr.net/gh/hhf443/blog-graph/img/20200508154922.png)]

  • 第一次握手:Client將SYN置1,隨機產生一個初始序列號seq發送給Server,進入SYN_SENT狀態;
  • 第二次握手:Server收到Client的SYN=1之後,知道客戶端請求建立連接,將自己的SYN置1,ACK置1,產生一個acknowledge number=sequence number+1,並隨機產生一個自己的初始序列號,發送給客戶端;進入SYN_RCVD狀態;
  • 第三次握手:客戶端檢查acknowledge number是否爲序列號+1,ACK是否爲1,檢查正確之後將自己的ACK置爲1,產生一個acknowledge number=服務器發的序列號+1,發送給服務器;進入ESTABLISHED狀態;服務器檢查ACK爲1和acknowledge number爲序列號+1之後,也進入ESTABLISHED狀態;完成三次握手,連接建立。

3.2.1 TCP建立連接可以兩次握手嗎?爲什麼?

不可以。有兩個原因:

  • 可能會出現已失效的連接請求報文段又傳到了服務器端

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

  • 其次,兩次握手無法保證Client正確接收第二次握手的報文(Server無法確認Client是否收到),也無法保證Client和Server之間成功互換初始序列號。

3.2.2 可以採用四次握手嗎?爲什麼?

可以。但是會降低傳輸的效率。

四次握手是指:第二次握手:Server只發送ACK和acknowledge number;而Server的SYN和初始序列號在第三次握手時發送;原來協議中的第三次握手變爲第四次握手。出於優化目的,四次握手中的二、三可以合併。

3.2.3 第三次握手中,如果客戶端的ACK未送達服務器,會怎樣?

Server端:
由於Server沒有收到ACK確認,因此會重發之前的SYN+ACK(默認重發五次,之後自動關閉連接進入CLOSED狀態),Client收到後會重新傳ACK給Server。

3.2.4 如果已經建立了連接,但客戶端出現了故障怎麼辦?

服務器每收到一次客戶端的請求後都會重新復位一個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。

3.2.5 初始序列號是什麼?

TCP連接的一方A,隨機選擇一個32位的序列號(Sequence Number)作爲發送數據的初始序列號(Initial Sequence Number,ISN),比如爲1000,以該序列號爲原點,對要傳送的數據進行編號:1001、1002…三次握手時,把這個初始序列號傳送給另一方B,以便在傳輸數據時,B可以確認什麼樣的數據編號是合法的;同時在進行數據傳輸時,A還可以確認B收到的每一個字節,如果A收到了B的確認編號(acknowledge number)是2001,就說明編號爲1001-2000的數據已經被B成功接受。

3.3 四次揮手

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WYCPtQSq-1588931594560)(https://cdn.jsdelivr.net/gh/hhf443/blog-graph/img/20200508160654.png)]

  • 第一次揮手:Client將FIN置爲1,發送一個序列號seq給Server;進入FIN_WAIT_1狀態;
  • 第二次揮手:Server收到FIN之後,發送一個ACK=1,acknowledge number=收到的序列號+1;進入CLOSE_WAIT狀態。此時客戶端已經沒有要發送的數據了,但仍可以接受服務器發來的數據。
  • 第三次揮手:Server將FIN置1,發送一個序列號給Client;進入LAST_ACK狀態;
  • 第四次揮手:Client收到服務器的FIN後,進入TIME_WAIT狀態;接着將ACK置1,發送一個acknowledge number=序列號+1給服務器;服務器收到後,確認acknowledge number後,變爲CLOSED狀態,不再向客戶端發送數據。客戶端等待2*MSL(報文段最長壽命)時間後,也進入CLOSED狀態。完成四次揮手。

3.3.1 爲什麼不能把服務器發送的ACK和FIN合併起來,變成三次揮手(CLOSE_WAIT狀態意義是什麼)?

因爲服務器收到客戶端斷開連接的請求時,可能還有一些數據沒有發完,這時先回復ACK,表示接收到了斷開連接的請求。等到數據發完之後再發FIN,斷開服務器到客戶端的數據傳送

3.3.2 如果第二次揮手時服務器的ACK沒有送達客戶端,會怎樣?

客戶端沒有收到ACK確認,會重新發送FIN請求。

3.3.3 客戶端TIME_WAIT狀態的意義是什麼?

第四次揮手時,客戶端發送給服務器的ACK有可能丟失,TIME_WAIT狀態就是用來重發可能丟失的ACK報文。如果Server沒有收到ACK,就會重發FIN,如果Client在2*MSL的時間內收到了FIN,就會重新發送ACK並再次等待2MSL,防止Server沒有收到ACK而不斷重發FIN

MSL(Maximum Segment Lifetime),指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。

3.4 流量控制

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YrOp4Vko-1588931594563)(https://github.com/wolverinn/Waking-Up/raw/master/_v_images/20191129145400104_2106.png)]

使用滑動窗口協議實現流量控制。防止發送方發送速率太快,接收方緩存區不夠導致溢出。接收方會維護一個接收窗口 receiver window(窗口大小單位是字節),接受窗口的大小是根據自己的資源情況動態調整的,在返回ACK時將接受窗口大小放在TCP報文中的窗口字段告知發送方。發送窗口的大小不能超過接受窗口的大小,只有當發送方發送並收到確認之後,才能將發送窗口右移

發送窗口的上限爲接受窗口和擁塞窗口中的較小值。接受窗口表明了接收方的接收能力,擁塞窗口表明了網絡的傳送能力。

3.4.1 什麼是零窗口(接收窗口爲0時會怎樣)?

接收方沒有能力接收數據,就會將接收窗口設置爲0,這時發送方必須暫停發送數據,但是會啓動一個持續計時器(persistence timer),到期後發送一個大小爲1字節的探測數據包,以查看接收窗口狀態。如果接收方能夠接收數據,就會在返回的報文中更新接收窗口大小,恢復數據傳送。

3.5 擁塞控制

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ntoThJQd-1588931594566)(https://github.com/wolverinn/Waking-Up/raw/master/_v_images/20191129153624025_28293.png)]

擁塞控制主要由四個算法組成:慢啓動(Slow Start)、擁塞避免(Congestion voidance)、快重傳 (Fast Retransmit)、快恢復(Fast Recovery)

  1. 慢啓動:剛開始發送數據時,先把擁塞窗口(congestion window)設置爲一個最大報文段MSS的數值,每收到一個新的確認報文之後,就把擁塞窗口加1個MSS。這樣每經過一個傳輸輪次(或者說是每經過一個往返時間RTT),擁塞窗口的大小就會加倍

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8bCCkU6d-1588931594575)(https://github.com/wolverinn/Waking-Up/raw/master/_v_images/20191129155345024_11142.png)]

  1. 擁塞避免:當擁塞窗口的大小達到慢開始門限(slow start threshold)時,開始執行擁塞避免算法,擁塞窗口大小不再指數增加,而是線性增加,即每經過一個傳輸輪次只增加1MSS.

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

  1. 快重傳:快重傳要求接收方在收到一個失序的報文段後就立即發出重複確認(爲的是使發送方及早知道有報文段沒有到達對方)而不要等到自己發送數據時捎帶確認。快重傳算法規定,發送方只要一連收到三個重複確認就應當立即重傳對方尚未收到的報文段,而不必繼續等待設置的重傳計時器時間到期。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-ZAhT5nvL-1588931594578)(https://github.com/wolverinn/Waking-Up/raw/master/_v_images/20191129161026032_32431.png)]

  1. 快恢復:當發送方連續收到三個重複確認時,就把慢開始門限減半,然後執行擁塞避免算法。不執行慢開始算法的原因:因爲如果網絡出現擁塞的話就不會收到好幾個重複的確認,所以發送方認爲現在網絡可能沒有出現擁塞。
    也有的快重傳是把開始時的擁塞窗口cwnd值再增大一點,即等於 ssthresh + 3*MSS 。這樣做的理由是:既然發送方收到三個重複的確認,就表明有三個分組已經離開了網絡。這三個分組不再消耗網絡的資源而是停留在接收方的緩存中。可見現在網絡中減少了三個分組。因此可以適當把擁塞窗口擴大些。

四、面試題

4.1 TCP與UDP的區別

  1. TCP是面向連接的,UDP是無連接的;(UDP發送數據之前不需要建立連接)
  2. TCP是可靠的,UDP不可靠;(UDP接收方收到報文後,不需要給出任何確認)
  3. TCP只支持點對點通信,UDP支持一對一、一對多、多對一、多對多;
  4. TCP是面向字節流的,UDP是面向報文的;(面向字節流是指發送數據時以字節爲單位,一個數據包可以拆分成若干組進行發送,而UDP一個報文只能一次發完。)
  5. TCP有擁塞控制機制,UDP沒有。網絡出現的擁塞不會使源主機的發送速率降低,這對某些實時應用是很重要的,比如媒體通信,遊戲;
  6. TCP首部開銷(20字節)比UDP首部開銷(8字節)要大
  7. UDP 的主機不需要維持複雜的連接狀態表

什麼時候選擇TCP,什麼時候選UDP?

對某些實時性要求比較高的情況,選擇UDP,比如遊戲,媒體通信,實時視頻流(直播),即使出現傳輸錯誤也可以容忍;其它大部分情況下,HTTP都是用TCP,因爲要求傳輸的內容可靠,不出現丟失

HTTP可以使用UDP嗎?

HTTP不可以使用UDP,HTTP需要基於可靠的傳輸協議,而UDP不可靠

面向連接和無連接的區別

無連接的網絡服務(數據報服務)-- 面向連接的網絡服務(虛電路服務)

虛電路服務:首先建立連接,所有的數據包經過相同的路徑,服務質量有較好的保證;

數據報服務:每個數據包含目的地址,數據路由相互獨立(路徑可能變化);網絡盡最大努力交付數據,但不保證不丟失、不保證先後順序、不保證在時限內交付;網絡發生擁塞時,可能會將一些分組丟棄;

4.2 TCP如何保證傳輸的可靠性

  1. 數據包校驗
  2. 對失序數據包重新排序(TCP報文具有序列號)
  3. 丟棄重複數據
  4. 應答機制:接收方收到數據之後,會發送一個確認(通常延遲幾分之一秒);
  5. 超時重發:發送方發出數據之後,啓動一個定時器,超時未收到接收方的確認,則重新發送這個數據;
  6. 流量控制:確保接收端能夠接收發送方的數據而不會緩衝區溢出
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章