前言
你們好啊,我是湯小圓。面試
今天給你們推薦的是,TCP/IP協議的經典面試知識點總結,但願對你們有幫助,謝謝。服務器
簡介
咱們平時常常聽到的TCP/IP
協議,實際上是一個協議族;網絡
只不過由於TCP、IP是其中最核心的協議,因此平時統稱爲TCP/IP協議;併發
這個協議族裏面還有其餘協議,好比HTTP
、FTP
、SMTP
等;框架
TCP分層框架
下圖是TCP/IP協議族的一個分層框架圖,從上往下依次是應用層、傳輸層、網絡層、鏈路層、物理層ide
假如我想在機器A上,發送一條"Hello World"到機器B,這個通信過程是個什麼樣子呢?測試
首先機器A的應用層將消息內容"Hello World"打包,而後經由傳輸層加上雙方的端口號,網絡層加上雙方的IP地址,鏈路層加上雙方的Mac地址,通過多個路由器和網關,最終到達機器B,而後機器B再反過來解析出消息內容"Hello World"url
簡化以後的路徑就是:消息實體+端口號+IP地址+Mac地址,封裝發送,收到消息後,再反過來解包操做spa
下面咱們從上往下,依次介紹各個分層的做用.net
應用層
按照固定的協議格式打包、解包數據。
好比SMTP協議,雖然不一樣公司的郵箱格式不盡相同,可是均可以解析對方發來的郵件內容,就是由於他們都遵循SMTP協議
傳輸層
決定數據要傳輸到遠程機器的哪一個程序(端口),同時要代表數據來自源機器的哪一個程序(端口),實現端口之間的通信。
好比本地跑一個測試程序A,監聽的是8080端口;遠程跑的測試程序B,監聽的是8080端口;
那麼傳輸層就會把本機的8080端口和遠程的8080端口都加到數據包上;
這樣遠程機器解析數據時,就知道要把數據傳給哪一個程序。
網絡層
指定雙方的IP地址,並進行路由的尋址和轉發
這裏要明白一點就是,遠程機器的IP地址不是一次跳轉就能夠到達的,要經過路由器和網關的屢次跳轉,纔會到達
這個能夠參考視頻《TCP/IP協議 - B站 - 馬士兵》
鏈路層
指定遠程機器的Mac地址(確保不會發錯地方),以及本機的Mac地址
既然有了Mac地址來做爲機器的惟一ID,爲啥還要有網絡層的IP地址呢?
緣由有兩個
-
IP是會變化的,有可能今天你跟機器A在聊天,明天就變成機器B了,固然會亂掉了
-
如今的電腦太多了,數以千萬計,從這麼多電腦中找出某一個Mac地址,效率很低;可是IP不同,IP是由網段劃分的,有點相似於郵編,這樣就能夠分段尋址,效率高不少
TCP的三次握手,四次揮手
三次握手
三次握手就是創建鏈接的過程,示意圖以下所示
咱們來再把流程簡化一點,就是:機器A發送鏈接請求到機器B -> 機器B收到後,確認併發送同步信號 -> 機器A收到確認信號後,再次發送確認信號到機器B
這裏面涉及到幾個關鍵詞,下面列出一一說明下
標誌關鍵詞
-
SYN(Synchronize Sequence Numbers),同步信號,表示打算創建鏈接時的一個信號
-
ACK(Acknowledgement),數據確認信號,表示是否確認收到數據
狀態關鍵詞
-
LISTENING,監聽狀態,表示還沒開始創建鏈接,正在監聽等待鏈接的到來
-
SYN_SENT,SYN已發送,表示SYN已經發送,可是成功不成功還不知道
-
SYN_RCVD,SYN已收到,表示收到SYN信號,也已經給了應答,可是鏈接還沒創建
-
ESTABLISHED,鏈接創建,表示雙方已經創建了鏈接,能夠開始相互通訊了
下面詳細說下三次握手的鏈接過程
-
機器A發送同步信號SYN=1,請求創建鏈接,並附帶序列號seq=x (機器A定義)
-
機器B收到鏈接請求(SYN=1),返回 同步信號SYN=1 和 數據確認信號ACK=1,並附帶序列號 seq = y(機器B本身定義),確認序列號 ack = x + 1(方便機器A校驗)
-
機器A收到機器B的反饋後,繼續發送 確認信號 ACK=1,並附帶序列號 seq = x + 1,確認序列號 ack = y + 1
爲何要三次?兩次行不行?
兩次也能夠,就是會出現髒鏈接和信息不對等問題。(開玩笑的,兩次固然不行了,出現這麼多問題,你們都不用通信了,天天光顧着創建鏈接了)
什麼是信息不對等?它是怎麼產生的呢?
信息不對等說的是,雙方對於對方的信息處理能力瞭解的不一致
對於機器A來講,它內部有四個跟報文收發能力有關的標誌(我發送成功了嗎,我接收成功了嗎,對方發送成功了嗎,對方接收成功了嗎)
那麼對於機器B來講,也應有這四個標誌
如今假設只有兩次握手,那麼當兩次握手完成後,機器A的四個標誌是都確認成功了,可是機器B內心卻會有個兩個疑問???
疑問1:我發送成功了嗎?
疑問2:對方接收成功了嗎?
這時就會產生信息的不對等。
就比如兩我的用對講機交流,我聽到你的講話了,我也迴應了,可是你忽然不理我了。那我就對本身的表達能力產生疑問了。。。
下面這個表格很形象的說明了 兩次握手致使信息不對等的問題
什麼是髒鏈接?它又是怎麼產生的呢?
瞭解髒讀以前要先明白一個知識點,就是報文存活的時間 > 請求鏈接的超時時間(通常狀況下)
如今假設咱們用的是兩次握手,那麼髒鏈接就是機器A有一次請求鏈接超時,而後請求重連,等到重連成功後,上一次超時的請求又來,此時這個請求對於機器B來講就是髒鏈接
下面是產生兩次握手產生髒鏈接的示意圖
從圖中能夠看到,從新發送的鏈接請求,兩次握手成功並斷開鏈接後,以前超時的請求又來了,此時機器B發送第二次握手,鏈接創建;
可是由於此時客戶端的狀態是ESTABLISHED(已創建鏈接),而不是SYN_SENT(同步信號已發送),因此機器A不認這個鏈接,沒法通信,也就成了髒鏈接。
四次揮手
四次揮手就是斷開鏈接的過程,示意圖以下所示
這裏面涉及到幾個上面沒提到的關鍵詞,下面列出一一說明下
標誌關鍵詞
-
FIN(Finish),完成信號,表示通信已經完成,接下來打算關閉鏈接了
狀態關鍵詞
-
FIN_WAIT_1,發送斷開鏈接後的等待狀態階段1,表示已經發送了 FIN 請求,可是對方還沒確認
-
FIN_WAIT_2,發送斷開鏈接後的等待狀態階段2,表示對方 ACK 確認了,可是對方還沒發送 FIN 請求
-
TIME_WAIT,固定時間等待期,表示對方已經發送了 FIN 請求 和 ACK 確認信號,我也發送了確認信號 ACK ,過一會就能夠關閉鏈接了
-
CLOSE_WAIT,關閉等待期,表示接收到 FIN 請求,併發送了 ACK 確認信號,這邊開始準備斷開鏈接的收尾工做
-
LAST_ACK,最後確認,表示已經發送了 FIN 請求和 ACK 確認信號,等待對方 ACK 確認就能夠關閉了
-
CLOSED,關閉狀態,表示已經關閉鏈接
下面詳細說下四次揮手的斷開鏈接過程
-
機器A發送 FIN 信號,請求關閉鏈接,並附帶序列號 seq = u
-
機器B收到 FIN 信號,返回 ACK 確認信號,並開始準備斷開鏈接的收尾工做
-
等到收尾完成,機器B再發送 FIN 信號 和 ACK 確認信號,並附帶序列號 seq = v, 確認序列號 ack = u + 1
-
機器A收到後,進入 TIME_WAIT 期,併發送 ACK 確認信號,附帶序列號 seq = u + 1,確認序列號 ack = v + 1
-
機器B收到後,關閉鏈接
-
機器A等待固定時間(2MSL,下面會介紹這個參數)後,也關閉鏈接
爲何握手是三次,揮手卻要四次呢?
由於揮手多了一個清理現場的部分,就是發送剩餘的數據,處理現場,關閉相關資源
其實若是沒有什麼能夠清理的,機器B也可能省略這個階段,而後在收到機器A的 FIN 信號時,直接返回 FIN 和 ACK 信號,這樣就會變成三次揮手
2MSL是什麼參數?
這個 2MSL 就是報文在網絡上的生存時長,意思就是報文若是在網絡上存在的時間超過這個參數,那麼報文就會自動丟棄
這個數值若是過大,會形成資源的浪費
由於若是數值過大,好多鏈接就會卡在TIME_WAIT這裏,還佔着端口,那麼這個端口就啥也不幹了
因此通常建議這個數值調小一點(建議小於30S),尤爲是在服務器端
那TIME_WAIT 這個階段能夠跳過嗎?爲何要在這裏等待一段時間呢?
不能夠,緣由有二
-
有可能機器A最後發完 ACK 確認信號後,對方沒收到,此時機器A若是立馬斷開鏈接,就會致使報文丟失;
相反的,正由於有了這個階段,因此當對方沒收到ACK信號時,對方過段時間會重發FIN+ACK信號,此時機器A會從新發送ACK信號,並從新計時
-
防止失效請求,防止已失效鏈接的請求數據包和正常鏈接的請求數據包混淆而發生異常
已失效的鏈接,指的是握手過程當中因爲某些緣由沒有成功,可是也沒斷開的鏈接
如今有了這個TIME_WAIT階段,那麼前面已失效的鏈接就會由於超時而被丟棄,從而不會干擾到正常的鏈接
總結
以上只是關於TCP/IP協議的簡單介紹,主要爲了小白入門;
想深刻細節的能夠參考《TCP/IP 核心技術卷一》和馬士兵老師的B站視頻
參考資料:
1. 《碼出高效:Java開發手冊》 2. 《TCP/IP 核心技術卷一》 3. B站馬士兵視頻:https://www.bilibili.com/video/BV1mA411q7Ry?p=7
圖片來源:以上全部圖片均來自《碼出高效 Java開發手冊》
後記
最後,感謝你們的觀看,謝謝。