[面試∙網絡] TCP/IP(四):TCP 與 UDP 協議簡介

從本章開始,咱們開始介紹最重要的傳輸層。傳輸層位於 OSI 七層模型的第四層(由下往上)。顧名思義,傳輸層的主要做用是實現應用程序之間的通訊。網絡層主要是保證不一樣數據鏈路下數據的可達性,至於如何傳輸數據則是由傳輸層負責。瀏覽器

傳輸層協議簡介

常見的傳輸層協議主要有 TCP 協議和 UDP 協議。TCP 協議是面向有鏈接的協議,也就是說在使用 TCP 協議傳輸數據以前必定要在發送方和接收方之間創建鏈接。通常狀況下創建鏈接須要三步,關閉鏈接須要四步。服務器

創建 TCP 鏈接後,因爲有數據重傳、流量控制等功能,TCP 協議可以正確處理丟包問題,保證接收方可以收到數據,與此同時還可以有效利用網絡帶寬。然而 TCP 協議中定義了不少複雜的規範,所以效率不如 UDP 協議,不適合實時的視頻和音頻傳輸。網絡

UDP 協議是面向無鏈接的協議,它只會把數據傳遞給接收端,可是不會關注接收端是否真的收到了數據。可是這種特性反而適合多播,實時的視頻和音頻傳輸。由於個別數據包的丟失並不會影響視頻和音頻的總體效果。指針

IP 協議中的兩大關鍵要素是源 IP 地址和目標 IP 地址。而剛剛咱們說過,傳輸層的主要做用是實現應用程序之間的通訊。所以傳輸層的協議中新增了三個要素:源端口號,目標端口號和協議號。經過這五個信息,能夠惟一識別一個通訊。cdn

不一樣的端口用於區分同一臺主機上不一樣的應用程序。假設你打開了兩個瀏覽器,瀏覽器 A 發出的請求不會被瀏覽器 B 接收,這就是由於 A 和 B 具備不一樣的端口。視頻

協議號用於區分使用的是 TCP 仍是 UDP。所以相同兩臺主機上,相同的兩個進程之間的通訊,在分別使用 TCP 協議和 UDP 協議時也能夠被正確的區分開來。blog

用一句話來歸納就是:「源 IP 地址,目標 IP 地址,源端口號,目標端口號和協議號」這五個信息只要有一個不一樣,都被認爲是不一樣的通訊。進程

UDP 首部

UDP 協議最大的特色就是簡單,它的首部以下圖所示:內存

UDP 首部

包長度表示 UDP 首部的長度和 UDP 數據長度之和。資源

校驗和用來判斷數據在傳輸過程當中是否損壞。計算這個校驗和的時候,不只考慮源端口號和目標端口號,還要考慮 IP 首部中的源 IP 地址,目標 IP 地址和協議號(這些又稱爲 UDP 僞首部)。這是由於以上五個要素用於識別通訊時缺一不可,若是校驗和只考慮端口號,那麼另外三個要素收到破壞時,應用就沒法得知。這有可能致使不應收到包的應用收到了包,該收到包的應用反而沒有收到。

這個概念一樣適用於即將介紹的 TCP 首部。

TCP 首部

和 UDP 首部相比,TCP 首部要複雜得多。解析這個首部的時間也相應的會增長,這是致使 TCP 鏈接的效率低於 UDP 的緣由之一。

TCP 首部

其中某些關鍵字段解釋以下:

  • 序列號:它表示發送數據的位置,假設當前的序列號爲 s,發送數據長度爲 l,則下次發送數據時的序列號爲 s + l。在創建鏈接時一般由計算機生成一個隨機數做爲序列號的初始值。

  • 確認應答號:它等於下一次應該接收到的數據的序列號。假設發送端的序列號爲 s,發送數據的長度爲 l,那麼接收端返回的確認應答號也是 s + l。發送端接收到這個確認應答後,能夠認爲這個位置之前全部的數據都已被正常接收。

  • 數據偏移:TCP 首部的長度,單位爲 4 字節。若是沒有可選字段,那麼這裏的值就是 5。表示 TCP 首部的長度爲 20 字節。

  • 控制位:改字段長度爲 8 比特,分別有 8 個控制標誌。依次是 CWR,ECE,URG,ACK,PSH,RST,SYN 和 FIN。在後續的文章中你會陸續接觸到其中的某些控制位。

  • 窗口大小:用於表示從應答號開始可以接受多少個 8 位字節。若是窗口大小爲 0,能夠發送窗口探測。

  • 緊急指針:盡在 URG 控制位爲 1 時有效。表示緊急數據的末尾在 TCP 數據部分中的位置。一般在暫時中斷通訊時使用(好比輸入 Ctrl + C)。

TCP 握手

TCP 是面向有鏈接的協議,鏈接在每次通訊前被創建,通訊結束後被關閉。瞭解鏈接創建和關閉的過程一般是考察的重點。鏈接的創建和關閉過程能夠用一張圖來表示:

TCP 鏈接創建和關閉

一般狀況下,咱們認爲客戶端首先發起鏈接。

三次握手創建鏈接

這個過程能夠用如下三句形象的對話表示:

  1. (客戶端):我要創建鏈接了。
  2. (服務端):我知道你要創建鏈接了,我這邊沒有問題。
  3. (客戶端):我知道你知道我要創建鏈接了,接下來咱們就正式開始通訊。

爲何是三次握手

根據通常的思路,咱們可能會以爲只要兩次握手就能夠了,第三步確認看似是多餘的。那麼 TCP 協議爲何還要費力不討好的加上這一次握手呢?

這是由於在網絡請求中,咱們應該時刻記住:「網絡是不可靠的,數據包是可能丟失的」。假設沒有第三次確認,客戶端向服務端發送了 SYN,請求創建鏈接。因爲延遲,服務端沒有及時收到這個包。因而客戶端從新發送一個 SYN 包。回憶一下介紹 TCP 首部時提到的序列號,這兩個包的序列號顯然是相同的。

假設服務端接收到了第二個 SYN 包,創建了通訊,一段時間後通訊結束,鏈接被關閉。這時候最初被髮送的 SYN 包剛剛抵達服務端,服務端又會發送一次 ACK 確認。因爲兩次握手就創建了鏈接,此時的服務端就會創建一個新的鏈接,然而客戶端以爲本身並無請求創建鏈接,因此就不會向服務端發送數據。從而致使服務端創建了一個空的鏈接,白白浪費資源。

在三次握手的狀況下,服務端直到收到客戶端的應答後纔會創建鏈接。所以在上述狀況下,客戶端會接受到一個相同的 ACK 包,這時候它會拋棄這個數據包,不會和服務端進行第三次握手,所以避免了服務端創建空的鏈接。

ACK 確認包丟失怎麼辦

三次握手其實解決了第二步的數據包丟失問題。那麼第三步的 ACK 確認丟失後,TCP 協議是如何處理的呢?

按照 TCP 協議處理丟包的通常方法,服務端會從新向客戶端發送數據包,直至收到 ACK 確認爲止。但實際上這種作法有可能遭到 SYN 泛洪攻擊。所謂的泛洪攻擊,是指發送方僞造多個 IP 地址,模擬三次握手的過程。當服務器返回 ACK 後,攻擊方故意不確認,從而使得服務器不斷重發 ACK。因爲服務器長時間處於半鏈接狀態,最後消耗過多的 CPU 和內存資源致使死機。

正確處理方法是服務端發送 RST 報文,進入 CLOSE 狀態。這個 RST 數據包的 TCP 首部中,控制位中的 RST 位被設置爲 1。這表示鏈接信息所有被初始化,原有的 TCP 通訊不能繼續進行。客戶端若是還想從新創建 TCP 鏈接,就必須從新開始第一次握手。

四次握手關閉鏈接

這個過程能夠用如下四句形象的對話表示:

  1. (客戶端):我要關閉鏈接了。
  2. (服務端):你那邊的鏈接能夠關閉了。
  3. (服務端):我這邊也要關閉鏈接了。
  4. (客戶端):你那邊的鏈接能夠關閉了。

因爲鏈接是雙向的,因此雙方都要主動關閉本身這一側的鏈接。

關閉鏈接的最後一個 ACK 丟失怎麼辦

實際上,在第三步中,客戶端收到 FIN 包時,它會設置一個計時器,等待至關長的一段時間。若是客戶端返回的 ACK 丟失,那麼服務端還會重發 FIN 並重置計時器。假設在計時器失效前服務器重發的 FIN 包沒有到達客戶端,客戶端就會進入 CLOSE 狀態,從而致使服務端永遠沒法收到 ACK 確認,也就沒法關閉鏈接。

示意圖以下:

TCP 關閉鏈接
相關文章
相關標籤/搜索