面試干貨:TCP/IP 協(xié)議的經(jīng)典面試知識點總結(jié)!
今天給大家推薦的是,TCP/IP協(xié)議的經(jīng)典面試知識點總結(jié),希望對大家有幫助,謝謝。

簡介
我們平時經(jīng)常聽到的TCP/IP協(xié)議,其實是一個協(xié)議族;
只不過因為TCP、IP是其中最核心的協(xié)議,所以平時統(tǒng)稱為TCP/IP協(xié)議;
這個協(xié)議族里面還有其他協(xié)議,比如HTTP、FTP、SMTP等;
TCP分層框架
下圖是TCP/IP協(xié)議族的一個分層框架圖,從上往下依次是應(yīng)用層、傳輸層、網(wǎng)絡(luò)層、鏈路層、物理層

假如我想在機器A上,發(fā)送一條"Hello World"到機器B,這個通訊過程是個什么樣子呢?
首先機器A的應(yīng)用層將消息內(nèi)容"Hello World"打包,然后經(jīng)由傳輸層加上雙方的端口號,網(wǎng)絡(luò)層加上雙方的IP地址,鏈路層加上雙方的Mac地址,經(jīng)過多個路由器和網(wǎng)關(guān),最終到達機器B,然后機器B再反過來解析出消息內(nèi)容"Hello World"
簡化之后的路徑就是:消息實體+端口號+IP地址+Mac地址,封裝發(fā)送,收到消息后,再反過來解包操作
下面我們從上往下,依次介紹各個分層的作用
應(yīng)用層
按照固定的協(xié)議格式打包、解包數(shù)據(jù)。
比如SMTP協(xié)議,雖然不同公司的郵箱格式不盡相同,但是都可以解析對方發(fā)來的郵件內(nèi)容,就是因為他們都遵循SMTP協(xié)議
傳輸層
決定數(shù)據(jù)要傳輸?shù)竭h程機器的哪個程序(端口),同時要表明數(shù)據(jù)來自源機器的哪個程序(端口),實現(xiàn)端口之間的通訊。
比如本地跑一個測試程序A,監(jiān)聽的是8080端口;遠程跑的測試程序B,監(jiān)聽的是8080端口;
那么傳輸層就會把本機的8080端口和遠程的8080端口都加到數(shù)據(jù)包上;
這樣遠程機器解析數(shù)據(jù)時,就知道要把數(shù)據(jù)傳給哪個程序。
網(wǎng)絡(luò)層
指定雙方的IP地址,并進行路由的尋址和轉(zhuǎn)發(fā)
這里要明白一點就是,遠程機器的IP地址不是一次跳轉(zhuǎn)就可以到達的,要通過路由器和網(wǎng)關(guān)的多次跳轉(zhuǎn),才會到達
鏈路層
指定遠程機器的Mac地址(確保不會發(fā)錯地方),以及本機的Mac地址
既然有了Mac地址來作為機器的唯一ID,為啥還要有網(wǎng)絡(luò)層的IP地址呢?
原因有兩個
IP是會變化的,有可能今天你跟機器A在聊天,明天就變成機器B了,當然會亂掉了
現(xiàn)在的電腦太多了,數(shù)以千萬計,從這么多電腦中找出某一個Mac地址,效率很低;但是IP不一樣,IP是由網(wǎng)段劃分的,有點類似于郵編,這樣就可以分段尋址,效率高很多
TCP的三次握手,四次揮手
三次握手
三次握手就是建立連接的過程,示意圖如下所示
我們來再把流程簡化一點,就是:機器A發(fā)送連接請求到機器B -> 機器B收到后,確認并發(fā)送同步信號 -> 機器A收到確認信號后,再次發(fā)送確認信號到機器B

這里面涉及到幾個關(guān)鍵詞,下面列出一一說明下
標志關(guān)鍵詞
SYN(Synchronize Sequence Numbers),同步信號,表示打算建立連接時的一個信號
ACK(Acknowledgement),數(shù)據(jù)確認信號,表示是否確認收到數(shù)據(jù)
狀態(tài)關(guān)鍵詞
LISTENING,監(jiān)聽狀態(tài),表示還沒開始建立連接,正在監(jiān)聽等待連接的到來
SYN_SENT,SYN已發(fā)送,表示SYN已經(jīng)發(fā)送,但是成功不成功還不知道
SYN_RCVD,SYN已收到,表示收到SYN信號,也已經(jīng)給了應(yīng)答,但是連接還沒建立
ESTABLISHED,連接建立,表示雙方已經(jīng)建立了連接,可以開始相互通信了
下面詳細說下三次握手的連接過程
機器A發(fā)送同步信號SYN=1,請求建立連接,并附帶序列號seq=x (機器A定義)
機器B收到連接請求(SYN=1),返回 同步信號SYN=1 和 數(shù)據(jù)確認信號ACK=1,并附帶序列號 seq = y(機器B自己定義),確認序列號 ack = x + 1(方便機器A校驗)
機器A收到機器B的反饋后,繼續(xù)發(fā)送 確認信號 ACK=1,并附帶序列號 seq = x + 1,確認序列號 ack = y + 1
為什么要三次?兩次行不行?
兩次也可以,就是會出現(xiàn)臟連接和信息不對等問題。(開玩笑的,兩次當然不行了,出現(xiàn)這么多問題,大家都不用通訊了,每天光顧著建立連接了)
什么是信息不對等?它是怎么產(chǎn)生的呢?
信息不對等說的是,雙方對于對方的信息處理能力了解的不一致
對于機器A來說,它內(nèi)部有四個跟報文收發(fā)能力有關(guān)的標志(我發(fā)送成功了嗎,我接收成功了嗎,對方發(fā)送成功了嗎,對方接收成功了嗎)
那么對于機器B來說,也應(yīng)有這四個標志
現(xiàn)在假設(shè)只有兩次握手,那么當兩次握手完成后,機器A的四個標志是都確認成功了,但是機器B心里卻會有個兩個疑問???
疑問1:我發(fā)送成功了嗎?
疑問2:對方接收成功了嗎?
這時就會產(chǎn)生信息的不對等。
就好比兩個人用對講機交流,我聽到你的講話了,我也回應(yīng)了,但是你突然不理我了。那我就對自己的表達能力產(chǎn)生疑問了。。。
下面這個表格很形象的說明了 兩次握手導致信息不對等的問題

什么是臟連接?它又是怎么產(chǎn)生的呢?
了解臟讀之前要先明白一個知識點,就是報文存活的時間 > 請求連接的超時時間(一般情況下)
現(xiàn)在假設(shè)我們用的是兩次握手,那么臟連接就是機器A有一次請求連接超時,然后請求重連,等到重連成功后,上一次超時的請求又來,此時這個請求對于機器B來說就是臟連接
下面是產(chǎn)生兩次握手產(chǎn)生臟連接的示意圖

從圖中可以看到,重新發(fā)送的連接請求,兩次握手成功并斷開連接后,之前超時的請求又來了,此時機器B發(fā)送第二次握手,連接建立;
但是因為此時客戶端的狀態(tài)是ESTABLISHED(已建立連接),而不是SYN_SENT(同步信號已發(fā)送),所以機器A不認這個連接,無法通訊,也就成了臟連接。
四次揮手
四次揮手就是斷開連接的過程,示意圖如下所示

這里面涉及到幾個上面沒提到的關(guān)鍵詞,下面列出一一說明下
標志關(guān)鍵詞
FIN(Finish),完成信號,表示通訊已經(jīng)完成,接下來打算關(guān)閉連接了
狀態(tài)關(guān)鍵詞
FIN_WAIT_1,發(fā)送斷開連接后的等待狀態(tài)階段1,表示已經(jīng)發(fā)送了 FIN 請求,但是對方還沒確認
FIN_WAIT_2,發(fā)送斷開連接后的等待狀態(tài)階段2,表示對方 ACK 確認了,但是對方還沒發(fā)送 FIN 請求
TIME_WAIT,固定時間等待期,表示對方已經(jīng)發(fā)送了 FIN 請求 和 ACK 確認信號,我也發(fā)送了確認信號 ACK ,過一會就可以關(guān)閉連接了
CLOSE_WAIT,關(guān)閉等待期,表示接收到 FIN 請求,并發(fā)送了 ACK 確認信號,這邊開始準備斷開連接的收尾工作
LAST_ACK,最后確認,表示已經(jīng)發(fā)送了 FIN 請求和 ACK 確認信號,等待對方 ACK 確認就可以關(guān)閉了
CLOSED,關(guān)閉狀態(tài),表示已經(jīng)關(guān)閉連接
下面詳細說下四次揮手的斷開連接過程
機器A發(fā)送 FIN 信號,請求關(guān)閉連接,并附帶序列號 seq = u
機器B收到 FIN 信號,返回 ACK 確認信號,并開始準備斷開連接的收尾工作
等到收尾完成,機器B再發(fā)送 FIN 信號 和 ACK 確認信號,并附帶序列號 seq = v, 確認序列號 ack = u + 1
機器A收到后,進入 TIME_WAIT 期,并發(fā)送 ACK 確認信號,附帶序列號 seq = u + 1,確認序列號 ack = v + 1
機器B收到后,關(guān)閉連接
機器A等待固定時間(2MSL,下面會介紹這個參數(shù))后,也關(guān)閉連接
為什么握手是三次,揮手卻要四次呢?
因為揮手多了一個清理現(xiàn)場的部分,就是發(fā)送剩余的數(shù)據(jù),處理現(xiàn)場,關(guān)閉相關(guān)資源
其實如果沒有什么可以清理的,機器B也可能省略這個階段,然后在收到機器A的 FIN 信號時,直接返回 FIN 和 ACK 信號,這樣就會變成三次揮手
2MSL是什么參數(shù)?
這個 2MSL 就是報文在網(wǎng)絡(luò)上的生存時長,意思就是報文如果在網(wǎng)絡(luò)上存在的時間超過這個參數(shù),那么報文就會自動丟棄
這個數(shù)值如果過大,會造成資源的浪費
因為如果數(shù)值過大,好多連接就會卡在TIME_WAIT這里,還占著端口,那么這個端口就啥也不干了
所以一般建議這個數(shù)值調(diào)小一點(建議小于30S),尤其是在服務(wù)器端
那TIME_WAIT 這個階段可以跳過嗎?為什么要在這里等待一段時間呢?
不可以,原因有二
有可能機器A最后發(fā)完 ACK 確認信號后,對方?jīng)]收到,此時機器A如果立馬斷開連接,就會導致報文丟失;
相反的,正因為有了這個階段,所以當對方?jīng)]收到ACK信號時,對方過段時間會重發(fā)FIN+ACK信號,此時機器A會重新發(fā)送ACK信號,并重新計時
防止失效請求,防止已失效連接的請求數(shù)據(jù)包和正常連接的請求數(shù)據(jù)包混淆而發(fā)生異常
已失效的連接,指的是握手過程中由于某些原因沒有成功,但是也沒斷開的連接
現(xiàn)在有了這個TIME_WAIT階段,那么前面已失效的連接就會因為超時而被丟棄,從而不會干擾到正常的連接
總結(jié)
以上只是關(guān)于TCP/IP協(xié)議的簡單介紹,主要為了小白入門。如果你想更好的提升你的編程核心能力(內(nèi)功)不妨從現(xiàn)在開始!
微信公眾號:C語言編程學習基地
整理分享(多年學習的源碼、項目實戰(zhàn)視頻、項目筆記,基礎(chǔ)入門教程)
歡迎轉(zhuǎn)行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
