TCP/IP協議棧——IP、TCP、UDP、HTTP協議詳解

2019-12-11     零聲度7

經過面試的同學經常會遇到這樣的問題: 你是如何理解TCP/IP協議的?
回答:通訊協議?三次握手 ? 四次揮手? 一臉懵逼!

如果你感覺已經被上述情景安排,那麼有必要好好看看這篇文章。

1 、什麼是協議

協議實際上就是一種約定。好比說,我們做一個石頭剪刀布的遊戲,我們約定好:石頭>剪刀、剪刀>布、布>石頭,以此作為遊戲規則。我們所有人都遵循這個約定,那麼就不需要任何的多餘的溝通便可以完成這個遊戲。而這種方式形成的約定實際上就是一種協議了。

2、TCP/IP協議簇

話聯網早期時,儘管知道計算機連接的原理,但是沒有協議的時候,就沒有辦法進行大規模的通信使用。當時就衍生出了很多為了解決當時問題的協議,像TCP協議就是為了約定大家使用TCP連接時傳輸的一種協議,HTTP協議則是為了約定文本傳輸的一種協議。

而TCP/IP協議並不是指某一個具體的協議,它是指代一系列的協議棧,因此也叫TCP/IP協議棧或者TCP/IP協議簇。

所以廣義上,我們說的TCP/IP指的是4層的總和。 而狹義上來說,指的是4層中的傳輸層和網絡互聯層。

在 TCP/IP協議簇 中,定義了包含對應 OSI 模型的每一層。但同時對 OSI 模型層做了簡化處理。看看這種圖理解一下:

TCP/IP層和OSI參考模型層的對應關係


也即是OSI模型中的7層,在TCP/IP中使用4層代替了。沒辦法,誰讓OSI那麼複雜呢。

在TCP/IP協議簇中每一層都有對應的協議,最終組成協議簇。

TCP/IP協議棧每一層的協議


我們經常說的TCPUDP在協議棧的傳輸層,而IP協議則在協議棧的網絡互聯層。還有經常被問到的HTTP協議實際上在協議棧的應用層。

TCP/IP協議棧被分作這麼多的層級,目的是為了整理硬體間通信時的一個通用的模型,因此它們每一層都和其上下層有關聯性的,如下圖:

TCP/IP協議棧數據封包分層

上面就是"TCP/IP協議"的總體概念了。但是其內部還有這麼多的協議,這裡挑幾個常見的講一講,從底層到上層:

IP協議 TCP協議 UDP協議 HTTP協議

2. 1 IP協議

IP協議處於TCP/IP協議簇的網絡互聯層。它提供不可靠、無連接的服務,也即依賴其他層的協議進行差錯控制。在區域網環境,IP協議往往被封裝在乙太網幀中傳送。而所有的TCP、UDP、ICMP、IGMP數據都被封裝在IP數據報中傳送。

在IP協議中,有兩個重要的內容需要了解下。一是IP位址的概念,二是IP協議的報頭。

2.1.1 IP位址的概念

其實對於IP位址我們日常接觸還是挺多的。它給每一個接入網際網路的計算器一個地址,從而使得其他的計算機能夠訪問到它。與此同時,當計算機有了地址之後,才能遵循IP協議,和其他的計算機進行數據的傳遞。

目前有兩種IP版本,分別是IPV4和IPV6。IPV4占用8個位元組32bit,而IPV6則是32個位元組128bit。IPV6的可用的數量極其龐大,大到全球每一粒沙子都可以分配一個IPV6地址。

以IPV4為例, IPV4的32bit地址中,分為兩個部分:網絡號和主機號。同時根據不同的內容開頭,又分為A、B、C、D、E類。

IPV4

網絡號用於區分不同的網絡點,比如一個公司是一個網絡集群,我們可以通過他的網絡號確定該公司網關,再通過主機號確定每一台計算。

假如一個C類的IP位址類型,包含了21位網絡號,實際上就能區分出 2^21 個網絡號,而在每一個網絡號中,可以區分 2^8 -2 = 254(起始的網絡號地址和最後一個為廣播地址都不可用於主機)個主機號。如果一個網吧採用這種方式的話,那麼他最多能安裝254台機器。如果我們想要得到更多的主機號,應該延長主機號的位數,但是相應的,網絡號的數量將減少,因為兩者的總長度是不變的。

通過掩碼能夠改變網絡號和主機號的位數。

通常,我們看到的掩碼類似:

255.255.255.0

二進位表示:

11111111.11111111.11111111.00000000

如果一個IPV4地址為:192.168.1.12
那麼IP位址和掩碼經過與運算之後的結果為:192.168.1.0(192.168.001.000), 這就是我們常說的網關!
而從 192.168.1.1~192.168.1.254都可作為主機號。也即是這個網關下,可以容納 254 台機器。

如果將掩碼更改為:

255.255.254.0

二進位表示:

11111111.11111111.11111110.00000000

那麼與運算的結果為:192.168.0.0 ,這時候可以使用的主機號就變成了 192.168.0.0 ~ 192.168.1.254, 即可容納 510 台機器。

2.1.2 IP尋址

當一個 IP 包從一台計算機被發送,它會到達一個 IP 路由器。

IP 路由器負責將這個包路由至它的目的地,直接地或者通過其他的路由器。

在一個相同的通信中,一個包所經由的路徑可能會和其他的包不同。而路由器負責根據通信量、網絡中的錯誤或者其他參數來進行正確地尋址。

2.1.3 IP協議的報頭

在上面的數據分層中,我們看到IP協議的構成實際上是 IP報頭 + TCP協議內容。

因此決定一個IP協議屬性的的關鍵是 IP報頭的內容。
下面我們來看下IP協議的組成,IPV4中普通的IP首部長20個位元組。其中有32位的源IP位址和32位的目的IP位址。

TTL:生存時間。代表了數據包可以經過的最多路由器數。比如TTL為10,意思是如果經過10次路由器轉發,仍然未找到目的地址,則報文丟棄

8位協議指示的是傳輸層承載的協議

16位總長度:指IP數據包的最大長度。16bit那麼最長可達65535位元組。但是通過鏈路的MTU不會有這麼大。因此如果數據包長度超過了MTU,數據包會被分片。如果發生了分片,則需要用到16位標識以及13位片偏移來找到分片的報文。

IP協議報頭

2.2 TCP協議
2.2.1 TCP協議作用

TCP協議位於協議棧的傳輸層。當應用層向TCP層發送用於網間傳輸的、用8位位元組表示的數據流,TCP則把數據流分割成適當長度的報文段,最大傳輸段大小(MSS)通常受該計算機連接的網絡的數據鏈路層的最大傳送單元(MTU)限制。之後TCP把數據包傳給IP層,由它來通過網絡將包傳送給接收端實體的TCP層。

TCP為了保證報文傳輸的可靠,就給每個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。然後接收端實體對已成功收到的位元組發回一個相應的確認(ACK);如果發送端實體在合理的往返時延(RTT)內未收到確認,那麼對應的數據(假設丟失了)將會被重傳。

  • 在數據正確性與合法性上,TCP用一個校驗和函數來檢驗數據是否有錯誤,在發送和接收時都要計算校驗和;同時可以使用md5認證對數據進行加密。
  • 在保證可靠性上,採用超時重傳和捎帶確認機制。
  • 在流量控制上,採用滑動窗口協議,協議中規定,對於窗口內未經確認的分組需要重傳。

在擁塞控制上,採用廣受好評的TCP擁塞控制算法(也稱AIMD算法)。
該算法主要包括三個主要部分:
(1)加性增、乘性減;
(2)慢啟動;
(3)對超時事件做出反應。

2.2.2 TCP的報頭

和IP協議一樣,TCP協議也有他的報頭部分。
以下即是圖示:


TCP報頭

  • 源埠:發送方的埠號
  • 目的埠:接受方的埠號 附: TCP和UDP埠號列表
  • 序號:發送方的序號
  • 確認序號:接受方得到序號之後回復的確認序號
  • TCP 首部長度:4 bits,以32-bit字為單位。TCP首部長短,也是TCP報文數據部分的偏移量。範圍5~15,即20 bytes ~ 60 bytes。可選項部分最多允許40 bytes。

標誌位,標誌位主要用戶標誌該報文當前的狀態。

URG:指示報文中有緊急數據,應儘快傳送(相當於高優先級的數據)。 ACK:確認序號(AN)有效。 PSH:接到後儘快交付給接收的應用進程。 RST:TCP連接中出現嚴重差錯(如主機崩潰),必須釋放連接,在重新建立連接。 SYN:處於TCP連接建立過程。 FIN:發送端已完成數據傳輸,請求釋放連接。

2.2.2 TCP協議的連接時候的三次握手

TCP是一個面向連接的協議,在每一次傳輸數據前,客戶端和服務端需要進行連接,這個連結就是著名的三次握手。

第一次:客戶端向服務端發送一個 SYN(SEQ=x 客戶端序號)報文給伺服器端,進入SYN_SEND狀態。

第二次:伺服器端收到SYN報文,回應一個SYN (SEQ=y 服務端序號)ACK(ACK=x+1 確認號=客戶端序號+1)報文,進入SYN_RECV狀態。

第三次:客戶端收到伺服器端的SYN報文,回應一個ACK(ACK=y+1)報文,進入Established狀態。

圖解:


TCP的三次握手

思考:為什麼要進行三次握手,而不是兩次呢? 比如在第一次握手之後,伺服器進入準備狀態,然後發送消息給客戶端,客戶端也進入準備狀態,這就完成了雙方的確認了。

  • 回答:兩次握手時,伺服器提前進入準備狀態之後,如果中途遇到網絡中斷,消息並沒有傳回給客戶端,客戶端將永遠接不到伺服器的給入狀態,那麼服務端將資源浪費在一個不存在的連接之上了。

思考2:三次握手就很安全了嗎?

  • 回答:在三次握手過程中,Server發送SYN-ACK之後,收到Client的ACK之前的TCP連接稱為半連接(half-open connect),此時Server處於SYN_RCVD狀態,當收到ACK後,Server轉入ESTABLISHED狀態。SYN攻擊就是Client在短時間內偽造大量不存在的IP位址,並向Server不斷地發送SYN包,Server回復確認包,並等待Client的確認,由於源地址是不存在的,因此,Server需要不斷重發直至超時,這些偽造的SYN包將產時間占用未連接隊列,導致正常的SYN請求因為隊列滿而被丟棄,從而引起網絡堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單,即當Server上有大量半連接狀態且源IP位址是隨機的,則可以斷定遭到SYN攻擊了,使用如下命令可以讓之現行:
#netstat -nap | grep SYN_RECV
2.2.3 TCP協議的斷開連接時候的四次揮手

既然TCP面向連接,那麼肯定也有斷開連接的操作。一個TCP完整的斷開需要進行四次揮手。

第一次:客戶端向服務端發送 FIN + ACK 報文,同時攜帶序號為 X。 客戶端進入 FIN-WAIT1

第二次:伺服器端回復 ACK 報文。附帶序號Z和確認序號X+1,表示伺服器已經接受到了客服端的報文。但是由於伺服器可能還在處理事務,因此,報文並不會攜帶FIN標誌。狀態:CLOSE WAIT

第三次:在一段時間之後,伺服器已經處理完畢,發送帶有 FIN和ACK的報文,序號為Y,確認序號為 X + 1 。 狀態: ACK-LAST

第四次:客戶端發送ACK報文,序號為 X+1,確認號Y+1 。 客戶端進入: TIME_WAIT。服務端進圖CLOSE(初始狀態)

TCP四次揮手

思考:為什麼建立連接是三次握手,而關閉連接卻是四次揮手呢?

  • 回答:這是因為服務端在LISTEN狀態下,收到建立連接請求的SYN報文後,把ACK和SYN放在一個報文里發送給客戶端。而關閉連接時,當收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即close,也可以發送一些數據給對方後,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送。

思考:為什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

  • 原因有二:
    一、保證TCP協議的全雙工連接能夠可靠關閉
    二、保證這次連接的重複數據段從網絡中消失
2.3 UDP協議

UDP協議全稱是用戶數據報協議,在網絡中它與TCP協議一樣用於處理數據包,兩者同處於協議棧的傳輸層,和TCP不同的是,UDP是一種無連接的協議。

因為UDP是無連接的,所以相對來說,UDP的報頭比TCP要簡單多了。


UDP報頭

UDP 特點
(1) UDP是一個非連接的協議,傳輸數據之前源端和終端不建立連接,當它想傳送時就簡單地去抓取來自應用程式的數據,並儘可能快地把它扔到網絡上。在發送端,UDP傳送數據的速度僅僅是受應用程式生成數據的速度、計算機的能力和傳輸帶寬的限制;在接收端,UDP把每個消息段放在隊列中,應用程式每次從隊列中讀一個消息段。
(2) 由於傳輸數據不建立連接,因此也就不需要維護連接狀態,包括收髮狀態等,因此一台服務機可同時向多個客戶機傳輸相同的消息。
(3) UDP信息包的標題很短,只有8個位元組,相對於TCP的20個位元組信息包的額外開銷很小。
(4) 吞吐量不受擁擠控制算法的調節,只受應用軟體生成數據的速率、傳輸帶寬、源端和終端主機性能的限制。
(5)UDP使用盡最大努力交付,即不保證可靠交付,因此主機不需要維持複雜的連結狀態表(這裡面有許多參數)。
(6)UDP是面向報文的。發送方的UDP對應用程式交下來的報文,在添加首部後就向下交付給IP層。既不拆分,也不合併,而是保留這些報文的邊界,因此,應用程式需要選擇合適的報文大小。

我們經常使用「ping」命令來測試兩台主機之間TCP/IP通信是否正常,其實「ping」命令的原理就是向對方主機發送UDP數據包,然後對方主機確認收到數據包,如果數據包是否到達的消息及時反饋回來,那麼網絡就是通的。

2.4 HTTP協議

HTTP協議名為超文本傳輸協議。這個協議在 TCP/IP 協議棧的應用層,因此我們無需操心HTTP是如何傳輸的,只需要關心,我們傳輸的內容,能否正確的被接收端識別。

HTTP 基於TCP實現,簡單來說,TCP協議負責可靠的內容傳輸,HTTP協議負責識別內容,兩者本身不在一個層面,沒有可比行。

HTTP無狀態的意思是,每一次的內容解析是沒有關聯的。TCP有狀態是指兩端在連接過程的。

HTTP包含兩種報文類型:請求報文、響應報文。請求報文用在客戶端對伺服器的請求時使用的報文格式,響應用在伺服器響應請求的報文格式。

2.4.1 HTTP協議請求消息結構

客戶端發送一個HTTP請求到伺服器的請求消息包括以下格式:請求行(request line)、請求頭部(header)、空行和請求數據四個部分組成,下圖給出了請求報文的一般格式。

HTTP請求消息體結構

HTTP消息體主要包含以下實質內容(空格和換行也必不可少):

請求方法 URL:統一資源定位符 HTTP請求頭部 HTTP請求體

以下是一個HTTP請求的例子:


HTTP請求實例

2.4.1.1 HTTP請求方法

HTTP包含了多種不同的請求方式,每一種請求方式用在不同的場景。

HTTP請求方法

2.4.1.2 URL —— 統一資源定位符

URL由三部分組成:資源類型、存放資源的主機域名、資源文件名。
URL的一般語法格式為:
(帶方括號[]的為可選項):
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
舉個例子: https://baijiahao.baidu.com/s?id=1603848351636567407&wfr=spider&for=pc

protocol:https
hostname:baijiahao.baidu.com
parameters:id=1603848351636567407&wfr=spider&for=pc (使用&分割參數)

總結一下如下圖:

附一張解析圖

2.4.1.3 HTTP請求頭

請求頭中主要包含本次請求的附加信息,其中常用的欄位如:

  • Accept: 指定客戶端能夠接收的內容類型
  • Accept-Encoding: 指定瀏覽器可以支持的web伺服器返回內容壓縮編碼類型。
  • Accept-Language: 瀏覽器可接受的語言
  • Content-Length 請求的內容長度 如:Content-Length: 348
  • Content-Type 請求的與實體對應的MIME信息,常用的類型
    image.png
  • Date 請求發送的日期和時間
    更多的請求頭欄位參考 HTTP響應頭和請求頭信息對照表
2.4.1.4 HTTP請求體

在整個報文中,請求頭之後,隔一行空格,以下部分就是HTTP的請求體了。
請求體是我們發送請求的時候需要傳給接收端的內容。其格式需要和請求頭中的Content-Type對應。不然會導致接受無法識別。
如上圖中的請求體: name=tom&password=1234

2.4.2 HTTP響應

HTTP的響應同樣分為:響應行、響應頭、響應體。和請求報文有點類似。
總體結構如圖:


HTTP響應報文

2.4.2.1 HTTP響應行

響應行中包含了HTTP的版本和本次請求的狀態。請求狀態的對應值見 HTTP響應碼大全.

2.4.2.2 HTTP響應頭

響應頭用於描述伺服器的基本信信息、數據的描述,這些信息將告知客戶端如何處理響應題中的內容。

  • Allow 伺服器支持哪些請求方法(如GET、POST等)。
  • Content-Encoding 文檔的編碼(Encode)方法。只有在解碼之後才可以得到Content-Type頭指定的內容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet應該通過查看Accept-Encoding頭(即request.getHeader("Accept-Encoding"))檢查瀏覽器是否支持gzip,為支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。
  • Content-Length 表示內容長度。只有當瀏覽器使用持久HTTP連接時才需要這個數據。如果你想要利用持久連接的優勢,可以把輸出文檔寫入 ByteArrayOutputStream,完成後查看其大小,然後把該值放入Content-Length頭,最後通過byteArrayStream.writeTo(response.getOutputStream()發送內容。
  • Content-Type 表示後面的文檔屬於什麼MIME類型。Servlet默認為text/plain,但通常需要顯式地指定為text/html。由於經常要設置Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。
    更多的響應頭欄位參考 HTTP響應頭和請求頭信息對照表
2.4.2.3 HTTP響應實體

響應實體中包含的就是客戶端從伺服器中獲取的數據了。數據的格式和長度都會在響應體頭中描述。

3. 更多的內容

除了 TCP/IP 協議棧的內容之外,還要諸如 ScoketHTTPS 協議等內容沒有再本文中介紹。主要是因為其他的內容相對來說形成一套體系,內容較多,將會在後續的文章中介紹。

小編整理了一些B-樹,B+樹的資料如下:

如果你也對Linux後台伺服器開發感興趣,想學習這方面的技術,後台私信【學習】免費獲取小編整理的一些資料(關注才能私信)

文章來源: https://twgreatdaily.com/kHGz9m4BMH2_cNUgY498.html