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

原文鏈接:https://www.jianshu.com/p/dac7b8bdb682

經過面試的同學經常會遇到這樣的問題: 你是如何理解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協議棧被分作這麼多的層級,目的是爲了整理硬件間通信時的一個通用的模型,因此它們每一層都和其上下層有關聯性的,如下圖:

8115459-8a676ef998f3fe0c.png (586Ã425)

上面就是"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位片偏移來找到分片的報文。

8115459-5f73a733ed036f38.png (538Ã363)
                                                     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協議也有他的報頭部分。
以下即是圖示:

8115459-8ecb92fc59d1450f.png (554Ã285)
                                                                    TCP報頭

  • 源端口:發送方的端口號
  • 目的端口:接受方的端口號
  • 序號:發送方的序號
  • 確認序號:接受方得到序號之後回覆的確認序號
  • 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狀態。。

圖解:

8115459-ecd0e38c3ff86d28.png (517Ã304)

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

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

思考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(初始狀態)。

8115459-9e5008104abf277e.png (720Ã438)

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

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

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

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

2.3 UDP協議

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

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

8115459-d5a87c443e51f732.png (485Ã175)

                                                                         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)、空行和請求數據四個部分組成,下圖給出了請求報文的一般格式。

8115459-b1eddeeb3feef61f.png (466Ã165)

                                 HTTP請求消息體結構

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

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

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

8115459-624e67bc40e7a0ce.png (801Ã430)

                                                                                    HTTP請求實例

2.4.1.1 HTTP請求方法

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

8115459-1ddbbed287957069.png (846Ã393)

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 (使用&分割參數)

總結一下如下圖:

8115459-59d5f5697e1601a2.png (640Ã120)

2.4.1.3 HTTP請求頭

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

  • Accept: 指定客戶端能夠接收的內容類型
  • Accept-Encoding: 指定瀏覽器可以支持的web服務器返回內容壓縮編碼類型。
  • Accept-Language: 瀏覽器可接受的語言
  • Content-Length 請求的內容長度 如:Content-Length: 348
  • Content-Type 請求的與實體對應的MIME信息,常用的類型

8115459-51293c81c41243e9.png (1000Ã547)

2.4.1.4 HTTP請求體

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

2.4.2 HTTP響應

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

8115459-963a353f17f57e35.png (572Ã264)

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 協議等內容沒有再本文中介紹。主要是因爲其他的內容相對來說形成一套體系,內容較多,將會在後續的文章中介紹。

後續:HTTPS協議的實現原理

來源:簡書
作者:BennyLoo
鏈接:https://www.jianshu.com/p/dac7b8bdb682

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章