動畫講解TCP,再不懂請來打我
TCP 三次握手和四次揮手過程對于面試是必考的一個,其中有些小細(xì)節(jié)也更受到面試官的青睞。
圖片來自 Pexels
對于這部分的掌握我將會以動畫的形式呈現(xiàn)給每個人,這樣將復(fù)雜的知識簡單化,理解起來也容易了很多,尤其對于一個初學(xué)者來說。
TCP 三次握手
思維導(dǎo)圖如下:
TCP 是什么
TCP(Transmission Control Protocol 傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。
我們知道了上述了解到了 TCP 的定義,通俗一點的講,TCP 就是一個雙方通信的一個規(guī)范標(biāo)準(zhǔn)(協(xié)議)。
我們在學(xué)習(xí) TCP 握手過程之前,首先必須了解 TCP 報文頭部的一些標(biāo)志信息。
因為在 TCP 握手的過程中,會使用到這些報文信息,如果沒有掌握這些信息,在學(xué)習(xí)握手過程中,整個人處于懵逼狀態(tài),也是為了能夠深入 TCP 三次握手的原理。
TCP 頭部報文
①Source Port 和 Distination Port
兩者分別為「源端口號」和「目的端口號」。源端口號就是指本地端口,目的端口就是遠(yuǎn)程端口。
一個數(shù)據(jù)包(Pocket)被解封裝成數(shù)據(jù)段(Segment)后就會涉及到連接上層協(xié)議的端口問題。
可以這么理解,我們可以想象發(fā)送方很多的窗戶,接收方也有很多的窗戶,這些窗口都標(biāo)有不同的端口號,源端口號和目的端口號就分別代表從哪個規(guī)定的串口發(fā)送到對方接收的窗口。
不同的應(yīng)用程度都有著不同的端口,之前網(wǎng)絡(luò)分層的文章中有提到過。
擴(kuò)展:應(yīng)用程序的端口號和應(yīng)用程序所在主機(jī)的 IP 地址統(tǒng)稱為 Socket(套接字),IP:端口號,在互聯(lián)網(wǎng)上 Socket 唯一標(biāo)識每一個應(yīng)用程序。
源端口+源 IP+目的端口+目的 IP 稱為“套接字對”,一對套接字就是一個連接,一個客戶端與服務(wù)器之間的連接。
②Sequence Number
稱為「序列號」。用于 TCP 通信過程中某一傳輸方向上字節(jié)流的每個字節(jié)的編號,為了確保數(shù)據(jù)通信的有序性,避免網(wǎng)絡(luò)中亂序的問題。
接收端根據(jù)這個編號進(jìn)行確認(rèn),保證分割的數(shù)據(jù)段在原始數(shù)據(jù)包的位置。
再通俗一點的講,每個字段在傳送中用序列號來標(biāo)記自己位置的,而這個字段就是用來完成雙方傳輸中確保字段原始位置是按照傳輸順序的。(發(fā)送方是數(shù)據(jù)是怎樣一個順序,到了接受方也要確保是這個順序)
PS:初始序列號由自己定,而后緒的序列號由對端的 ACK 決定:SN_x = ACK_y(x 的序列號 = y 發(fā)給 x 的 ACK),這里后邊會講到。
③Acknowledgment Number
稱為「確認(rèn)序列號」。確認(rèn)序列號是接收確認(rèn)端所期望收到的下一序列號。確認(rèn)序號應(yīng)當(dāng)是上次已成功收到數(shù)據(jù)字節(jié)序號加 1,只有當(dāng)標(biāo)志位中的 ACK 標(biāo)志為 1 時該確認(rèn)序列號的字段才有效,主要用來解決不丟包的問題。
若確認(rèn)號=N,則表明:到序號 N-1 為止的所有數(shù)據(jù)都已正確收到。
在這里,現(xiàn)在我們只需知道它的作用是什么,就是在數(shù)據(jù)傳輸?shù)臅r候是一段一段的,都是由序列號進(jìn)行標(biāo)識的,所以說,接收端每接收一段,之后就想要的下一段的序列號就稱為「確認(rèn)序列號」。
④TCP Flag
TCP 首部中有 6 個標(biāo)志比特,它們中的多個可同時被設(shè)置為 1,主要是用于操控 TCP 的狀態(tài)機(jī)的,依次為 URG,ACK,PSH,RST,SYN,F(xiàn)IN。
不要求初學(xué)者全部掌握,在這里只講三個重點的標(biāo)志:
ACK:這個標(biāo)識可以理解為發(fā)送端發(fā)送數(shù)據(jù)到接收端,發(fā)送的時候 ACK 為 0,標(biāo)識接收端還未應(yīng)答,一旦接收端接收數(shù)據(jù)之后,就將 ACK 置為 1,發(fā)送端接收到之后,就知道了接收端已經(jīng)接收了數(shù)據(jù)。
此標(biāo)志表示「應(yīng)答域有效」,就是說前面所說的 TCP 應(yīng)答號將會包含在 TCP 數(shù)據(jù)包中;有兩個取值:0 和 1,為 1 的時候表示應(yīng)答域有效,反之為 0。
SYN:表示「同步序列號」,是 TCP 握手的發(fā)送的第一個數(shù)據(jù)包。
用來建立 TCP 的連接。SYN 標(biāo)志位和 ACK 標(biāo)志位搭配使用,當(dāng)連接請求的時候,SYN=1,ACK=0 連接被響應(yīng)的時候,SYN=1,ACK=1;這個標(biāo)志的數(shù)據(jù)包經(jīng)常被用來進(jìn)行端口掃描。
掃描者發(fā)送一個只有 SYN 的數(shù)據(jù)包,如果對方主機(jī)響應(yīng)了一個數(shù)據(jù)包回來 ,就表明這臺主機(jī)存在這個端口。
看下面動畫:
FIN:表示發(fā)送端已經(jīng)達(dá)到數(shù)據(jù)末尾,也就是說雙方的數(shù)據(jù)傳送完成,沒有數(shù)據(jù)可以傳送了,發(fā)送 FIN 標(biāo)志位的 TCP 數(shù)據(jù)包后,連接將被斷開。這個標(biāo)志的數(shù)據(jù)包也經(jīng)常被用于進(jìn)行端口掃描。
這個很好理解,就是說,發(fā)送端只剩最后的一段數(shù)據(jù)了,同時要告訴接收端后邊沒有數(shù)據(jù)可以接受了,所以用 FIN 標(biāo)識一下,接收端看到這個 FIN 之后,哦!這是接受的最后的數(shù)據(jù),接受完就關(guān)閉了。
動畫如下:
Window Size:稱為滑動窗口大小。所說的滑動窗口,用來進(jìn)行流量控制。
為什么進(jìn)行 TCP 三次握手
原因如下:
- 為了確認(rèn)雙方的接收與發(fā)送能力是否正常。
- 指定自己的初始化序列號,為后面的可靠傳送做準(zhǔn)備。
- 如果是 HTTPS 協(xié)議的話,三次握手這個過程,還會進(jìn)行數(shù)字證書的驗證以及加密密鑰的生成到。
如果你了解 UDP 的話,TCP 的出現(xiàn)正式彌補(bǔ)了 UDP 不可靠傳輸?shù)娜秉c。但是 TCP 的誕生,也必然增加了連接的復(fù)雜性。
TCP 三次握手過程
TCP 三次握手的過程掌握最重要的兩點就是客戶端和服務(wù)端狀態(tài)的變化,另一個是三次握手過程標(biāo)志信息的變化,那么掌握 TCP 的三次握手就簡單多了。
下面我們就以動畫形式進(jìn)行拆解三次握手過程:
初始狀態(tài):客戶端處于 Closed(關(guān)閉)狀態(tài),服務(wù)器處于 Listen(監(jiān)聽)狀態(tài)。
第一次握手:客戶端發(fā)送請求報文將 SYN=j(1)初始化序列號發(fā)送給客戶端,發(fā)送完之后客戶端處于 SYN_Send 狀態(tài)。
第二次握手:服務(wù)端受到 SYN 請求報文之后,如果同意連接,會以自己的SYN(服務(wù)端)=K(0)和 ack(1)=SYN(客戶端)+1(ACK=1)報文作為應(yīng)答,服務(wù)器為 SYN_Receive 狀態(tài)。
第三次握手:客戶端接收到服務(wù)端的 SYN+ACK,然后發(fā)送 ack=SYN(服務(wù)端)+1(ACK=1)確認(rèn)包作為應(yīng)答,客戶端轉(zhuǎn)為 Established 狀態(tài)。
為什么不是一次、兩次握手
防止了服務(wù)器端的一直等待而浪費資源。為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤。
如果此時客戶端發(fā)送的延遲的握手信息服務(wù)器收到,然后服務(wù)器進(jìn)行響應(yīng),認(rèn)為客戶端要和它建立連接,此時客戶端并沒有這個意思。
但 Server 卻以為新的運輸連接已經(jīng)建立,并一直等待 Client 發(fā)來數(shù)據(jù)。這樣,Server 的很多資源就白白浪費掉了。
TCP 四次分手
下面我們接著用生動有趣的動畫給大家分享 TCP 四次揮手(分手)過程。
思維導(dǎo)圖如下:
為何要 TCP 三次握手/四次分手
TCP 的三次握手和四次分手和你戀愛是一模一樣的,從相識到相戀到分手,然后認(rèn)識另一個女孩再不管重復(fù)這個過程就是數(shù)據(jù)傳輸在網(wǎng)絡(luò)中不斷建立起三次握手和四次分手過程。
戀愛就戀愛吧,分手就分手吧,握手握來握去,揮手揮來揮去不嫌麻煩嗎?
因為上篇文章 TCP 三次握手中的為什么要進(jìn)行三次握手部分講解的不怎么詳細(xì),于是我就收集了一些資料,做了一個總結(jié),在這里補(bǔ)充下。
①為什么要進(jìn)行三次握手?
在謝希仁著《計算機(jī)網(wǎng)絡(luò)》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端,因而產(chǎn)生錯誤”。
舉個簡單易懂的例子,你在微信對一個女孩表白,這條信息由于網(wǎng)絡(luò)問題延遲發(fā)送了。
然后此時你不耐煩了,去和微信另一個女孩表白,然后另一個女孩告訴你同意了,然后你心里很高興,把高興的心情分享給了女孩,女孩知道了你和她在一起很高興,此時三次握手完畢,你戀愛了。
突然,到了第二天,發(fā)給第一個女孩的信息才收到,女孩認(rèn)為你要和他表白,此時你已經(jīng)和另一個女孩戀愛了,然后第一個女孩給你發(fā)微信同意了你的表白,但是你不理睬,那個女孩還在苦苦等待你給她分享此時的高興心情。
現(xiàn)在我們發(fā)現(xiàn)如果沒有分享高興的心情給女孩(也就是第三次握手過程),那么那個女孩一直等待,白白浪費了心思,所謂的千年都等不了一回。
如果你是客戶端,女孩是服務(wù)端,服務(wù)端收到延遲的報文,以為你要和它連接,所以會給你發(fā)送確認(rèn)同意連接,但你一直不搭理它,所以服務(wù)端的資源也就這么白白浪費掉了。所以知道為什么要進(jìn)行三次握手了吧。
在《計算機(jī)網(wǎng)絡(luò)》書中講“三次握手”的目的是為了解決“網(wǎng)絡(luò)中存在延遲的重復(fù)分組”的問題。
②為什么要 TCP 四次分手?
我們知道,TCP協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的運輸層通信協(xié)議,而且 TCP 是全雙工模式。
對于初學(xué)者來說,定義太枯燥、無味,其實意思就是你和你女朋友聊天是面向連接的,只有連接起來才可以通信的。
可靠就是你發(fā)送的信息可以保證送達(dá)到對方,全雙工意思就是你不僅可以給你女朋友發(fā)消息,而且她也可以給你發(fā)信息。
為什么非要進(jìn)行 TCP 四次分手?我們接著上回說到,你現(xiàn)在和第二個女孩子戀愛了,突然有一天發(fā)現(xiàn)第一個女孩子是因為沒有收到你的表白而錯過了在一起的時機(jī),那么你要和第二個女孩子分手。
那過程對應(yīng)在 TCP 四次分手是怎么樣子的?
你要給第二個女孩子微信發(fā)消息,我們分手吧,此時第二個女孩子收到消息知道了,非常傷心,就屏蔽了你。
但是,此時你還沒有屏蔽她,她完全可以給你繼續(xù)發(fā)消息,她給你發(fā)消息說,好吧,此時你收到了確認(rèn)消息,此時是第二次分手過程。那么女孩又給你發(fā)送消息,渣男,永遠(yuǎn)不要來找我。
此時你又接收到消息,看到消息之后發(fā)了一個拜拜,然后你就直接屏蔽拉黑了對方,此時女孩微信顯示你刪除了對方,然后就把你也拉黑刪除了。那么四次分手到此為止,恭喜你,成功獲得下一個女孩子。
上述過程就闡述了為什么要進(jìn)行 TCP 四次分手,為了能夠讓對方屏蔽你直至最后雙方互相刪除掉,然后你又可以和另一個女孩三次握手了。
TCP 四次分手過程
初始化狀態(tài):客戶端和服務(wù)端都在連接狀態(tài),接下來開始進(jìn)行四次分手?jǐn)嚅_連接操作。
第一次分手:第一次分手無論是客戶端還是服務(wù)端都可以發(fā)起,因為 TCP 是全雙工的。
假如客戶端發(fā)送的數(shù)據(jù)已經(jīng)發(fā)送完畢,發(fā)送 FIN=1 告訴服務(wù)端,客戶端所有數(shù)據(jù)已經(jīng)全發(fā)完了,服務(wù)端你可以關(guān)閉接收了,但是如果你們服務(wù)端有數(shù)據(jù)要發(fā)給客戶端,客戶端照樣可以接收的。
此時客戶端處于 FIN=1 等待服務(wù)端確認(rèn)釋放連接狀態(tài)。
第二次分手:服務(wù)端接收到客戶端的釋放請求連接之后,知道客戶端沒有數(shù)據(jù)要發(fā)給自己了,然后服務(wù)端發(fā)送 ACK=1 告訴客戶端受到你發(fā)給我的信息,此時服務(wù)端處于 CLOSE_WAIT 等待關(guān)閉狀態(tài)。
第三次分手:此時服務(wù)端向客戶端把所有的數(shù)據(jù)發(fā)送完了,然后發(fā)送一個 FIN=1,用于告訴客戶端,服務(wù)端的所有數(shù)據(jù)發(fā)送完畢,客戶端你也可以關(guān)閉接受數(shù)據(jù)連接了。
此時服務(wù)端狀態(tài)處于 LAT_ACK 狀態(tài),來等待確認(rèn)客戶端是否收到了自己的請求。
第四次分手:此時如果客戶端收到了服務(wù)端發(fā)送完的信息之后,就發(fā)送 ACK=1,告訴服務(wù)端,客戶端已經(jīng)收到了你的信息。但是我們發(fā)現(xiàn)上圖中有一個 2 MSL 的延遲等待。
為什要有 2MSL 等待延遲
對應(yīng)這樣一種情況,最后客戶端發(fā)送的 ACK=1 給服務(wù)端的過程中丟失了,服務(wù)端沒收到,服務(wù)端怎么認(rèn)為的?我已經(jīng)發(fā)送完數(shù)據(jù)了,怎么客戶端沒回應(yīng)我?是不是中途丟失了?
然后服務(wù)端再次發(fā)起斷開連接的請求,一個來回就是 2MSL,這里的兩個來回由那一個來回組成的?
客戶端給服務(wù)端發(fā)送的 ACK=1 丟失,服務(wù)端等待 1MSL 沒收到,然后重新發(fā)送消息需要 1MSL。
如果再次接收到服務(wù)端的消息,則重啟 2MSL 計時器,發(fā)送確認(rèn)請求。客戶端只需等待 2MSL,如果沒有再次收到服務(wù)端的消息,就說明服務(wù)端已經(jīng)接收到自己確認(rèn)消息;此時雙方都關(guān)閉的連接,TCP 四次分手完畢。
如果雙方建立連接,一方出問題
如果雙方建立連接,一方出問題怎么辦?為了防止出現(xiàn)上述戀愛故事中千年等一回的情況,已經(jīng)建立連接,但是服務(wù)端一直等待接收,發(fā)送端出現(xiàn)問題一直不能發(fā)送。
所以設(shè)計一個?;畹挠嫊r器,如果一方出現(xiàn)問題,另一方過了這個計時器的時間,就發(fā)送試探報文,以后每隔 75 秒發(fā)送一次。若一連發(fā)送 10 個探測報文仍然沒反應(yīng),服務(wù)器就認(rèn)為客戶端出了故障,接著就關(guān)閉連接。
最后為大家整理的三次握手和四次分手整張圖,如下:
最后希望你和你的女朋友永遠(yuǎn)三次握手,永不四次分手。