首先來說一下TCP"三次握手四次揮手"來創建鏈接這個說法的來源,其實真正的在官方的文檔中是經過handshake這個單詞描述"整個創建-斷開鏈接"的過程,因此三次報文傳送創建鏈接和四次報文傳送斷開鏈接的整個過程才稱得上一次握手.面試
很形象的說就像咱們平常生活正握手同樣,創建鏈接的時候至關於把手握在一塊兒,其次咱們會互相說你好,很久不見之類的話,這就像創建鏈接以後傳送的一些信息,最後咱們互相問候以後會把握在一塊兒的手鬆開,這個時候就像斷開鏈接,經過這樣一個詳細的握手-講話-鬆手例子,咱們就能夠清晰地理解客戶機(client)和服務器(server)從創建鏈接到傳送信息最後再到斷開鏈接.服務器
在經過糾正理解(重要)部分以後咱們能夠對整個過程有了清晰的認識,下面這一部分咱們專一於握手-講話-鬆手中的握手(創建鏈接)的是怎麼握的.網絡
圖一👇spa
圖二👇server
咱們從上往下看,blog
首先(第一步)路由
看客戶機(client)和服務器的鏈接都是LISTEN(監聽)或者CLOSED(關閉)狀態。文檔
這個無所謂了, 咱們繼續向下看,握手的發起者是客戶機(client),客戶機會主動打開鏈接通道經過網關路由向服務器發送一條報文(SYN(SYNbit) = 1, seq = x),客戶機(client)的狀態從LISTEN(監聽)或者CLOSE(關閉)狀態(狀態1)轉換爲發送同步號狀態(SYN-SENT)(狀態2)。同步
這條報文包含兩個部分,第一部分是SYN(同步號\同步器,反正就是同步的意思啦,這裏叫作同步標誌位好啦),seq(序列,就是和同步標誌位一塊兒工做的兄弟),而後它倆兄弟過千山萬水到達了服務器。it
服務器監聽到了信息,打開大門接收了這倆兄弟(同步號標誌位SYN=1和同步序列seq=x),這個時候服務器狀態就從LITSTEN(監聽)或者CLOSE(關閉)轉爲了SYN RCVD(收到同步標誌位和同步序列了)狀態。
第一個報文完成(客戶機到服務器)!
接着(第二步)
服務器收到了客戶機請求創建鏈接的消息以後,選擇應答客戶機,就會發送本次應答的信息。
這個信息包括本次的SYN=1(同步標誌位)和seq=y(序列y),除此以外還有ACK(應答標誌位)和ack(應答數字,應答數字是接收的標誌序列seq+1)。同步標誌位(SYNbit)和應答標誌位(ACKbit)都是標誌着一條消息(對應的是seq和ack或者ACKnum)是什麼類型的,咱們能夠把SYN和ACK理解爲咱們寫文章時候的標題,seq和ACKnum或ack理解爲文章正文。
而後客戶機收到這個回覆以後,經過ack或者ACKnum(應答數字)和本身發過去的同步序列seq進行比對,發現正好ack是本身發過去的seq + 1,這樣就證實了服務器活着,而且還收到了本身發送的創建鏈接請求。
這個時候客戶機的狀態就從發送同步信號狀態(SYN-SENT)(狀態2)轉換成了鏈接創建狀態(ESTABLISHED)(狀態3)。
第二個報文完成(服務器到客戶機)!
最後(第三步)
前兩步就已經互通了,就能夠創建鏈接了,爲何還要第三步呢?咱們這裏先把第三步走完,最後再單獨分析這一步,這一步也是面試中的關鍵一步!
客戶機在收到了服務器的贊成信息(服務器確認信息)以後,客戶機會再一次的發送報文給客戶機,發送的內容依舊是和服務器發送回來的格式同樣,兩大部分(同步信息和標誌信息),四小部分(同步號和同步序列;標誌號和標誌數字),爲何格式是同樣的呢?是由於從服務器發送回到客戶機和如今最後一步的目的是相同的;
服務器發送信息回到客戶機的目的是爲了應答客戶機的同步信息(SYN=1和seq=x),這一步的目的一樣明顯,是爲了應答服務器的同步信息(SYN=1和seq=y),咱們知道了這兩條消息的目的相同,那麼咱們就很容易理解到,ack或者ACKnum確定是y+1了(從服務器的seq = x + 1 推斷出來的),SYN和ACK確定是1,咱們能夠發現,標誌位ACK對應的的ack或者ACKnum老是收到消息的seq+1, 咱們沒有推斷錯誤。
服務器收到這條消息以後呢,服務器就能夠知道客戶機也還活着,而且ack活着ACKnum對應的正好是本身剛發過去的seq+1,也證實信息沒收錯(這裏都是形象比喻,方便理解),這時候服務器的狀態也會從SYN RCVD轉換爲ESTABLISHED。
第三步完成了(客戶機到服務器)!
爲何還要第三步呢?
解決這個問題時,咱們須要先了解一下發送報文的機制,在網絡中發送報文時會先發送第一次報文,而後有一個超時機制,超時結束後沒收到回覆會再次發送一次報文,還有在網絡中咱們從客戶機到服務器能夠有不少的路線選擇,在瞭解了這兩個機制以後咱們能夠繼續向下分析了。
咱們經過一種假設狀況來理解爲何還須要第三步:
假如咱們沒有第三步,
假設咱們第一次從客戶機發送報文到服務器請求鏈接,而後因爲網絡情況不好,咱們這一個報文被阻塞在了某個路由器中,沒有送達到服務器,因此服務器就一直沒有相應咱們的請求,咱們客戶機超時都沒有收到服務器的反饋,接着基於咱們前面講的報文發送機制能夠推出,咱們客戶機還會再一次發送請求報文過去,第二次發送的請求報文選擇的路線很好,瞬間到達了服務器,服務器收到後當即進行了反饋,返回了確認信息,假如沒有第三步,這時候咱們鏈接已經創建起來了!
咱們是經過超時發送的第二次報文創建的鏈接,若是第一次阻塞的請求這個時候路線又通了,那麼服務器又收到了一次請求,服務器又當即反饋了,這個時候因爲沒有第三步,到這裏創建鏈接的兩步已經走完了,因此咱們就創建了兩個鏈接。
如今咱們有了第三步,
從圖中咱們看到,咱們給服務器通過第三步發過去的seq是基於第一步請求的seq再+1,這樣若是被阻塞的第一次請求路線通了,服務器再次反饋回來,咱們發現這個時候咱們並無給服務器請求(超時發送第二條請求以後第一條請求咱們客戶機就直接拋棄了,認爲它再也不有效),可是服務器怎麼平白無故又反饋了呢,基於上面沒有第三步,若是沒有第三步,到目前爲止,創建鏈接的兩個步驟已經完成,這一步是否是服務器又給咱們完成了一次創建鏈接,可是有了第三步,注意!咱們客戶機發現是這種狀況以後,就不會再執行第三步了,這樣創建鏈接的三步沒有執行完,因此就不能成功的再一次創建鏈接。這裏也是面試的重點!
到如今爲止,咱們完全明白了創建鏈接的整個過程,其中具體怎麼樣掃描端口的啊,怎麼傳輸的啊咱們不須要了解,只要知道怎麼個過程就能夠了!固然,網絡工程師除外。
通過這三次報文傳送,鏈接已經創建好了,這樣整個"握手-說話-鬆手" 的 握手環節結束了,如今的狀態就是雙方手已經握在一塊兒了。
這裏不是咱們關注的重點,略,咱們看下面的四次報文鬆手環節!
在理解了三次報文創建鏈接以後,咱們再來理解一下四次報文傳送斷開鏈接,經過上面的兩張圖來幫助理解,我以爲這兩張圖畫的都很好,上邊是國外畫的,我加了一些中文註釋,下邊是中文圖書上畫的。
下面這一部分咱們專一於握手-講話-鬆手中的鬆手(斷開鏈接)是怎麼鬆的.
第一步(客戶機請求結束到服務器):
客戶機和服務器都是鏈接狀態,這個時候客戶機已經不須要再發送數據到服務器了,會主動發送一個結束標誌FIN和對應的序列seq,這時候客戶機就進入了FIN-WAIT-1結束等待階段1,這個時候客戶機已經不可以再給服務器發送了,只要發了結束標誌FIN就不可以再發送數據包了,可是能夠繼續接收服務器發來的數據,等下服務器也是同樣的。數據包和結束標誌和應答標誌是不同的,不能發送數據包但能夠發應答標誌。
第二步(服務器反饋到客戶機):
服務器收到客戶機的斷開請求以後會給客戶機一個反饋,一樣遵循ack = seq + 1,這個返回發送以後,服務器會進入關閉等待階段CLOSE-WAIT,可是服務器仍然能夠給客戶機發送數據包,由於服務器只是給客戶機發送了應答標誌可應答數,這個時候服務器若是還有數據須要發送給客戶機,會繼續給客戶機發送數據,客戶機接收到服務器的應答反饋,此時客戶機從FIN-WAIT-1階段到達FIN-WAIT-2階段,若是服務器還有數據發來,仍可以接收。
第三步(服務器請求結束到客戶機):
接着,服務器若是沒有數據要發給客戶機,也會向客戶機那樣請求結束,這裏會有一個新的seq,專屬於服務器發來的seq是w,在服務器發送完這個結束請求以後服務器會進入到LAST-ACK階段,即等待客戶機的響應。
第四步(客戶機迴應服務器):
最後客戶機收到服務器的請求以後,會當即給服務器回覆一個確認響應,告訴服務器我知道了,可是這裏客戶機按照咱們的理解應該能夠關閉鏈接了,可是並無,客戶機會接着進入一個時長爲2MSL的等待,大概是兩個超時時間(超時就是前面創建鏈接時說的那個超時)。至於爲何沒有當即關閉的緣由這是個面試重點,後面我會單獨介紹爲何,客戶機的迴應服務器收到以後會當即關閉鏈接,而後客戶機的等待時間到了也會關閉鏈接,客戶機和服務器至此流浪各天涯!
爲何客戶機給服務器發送確認響應以後沒有當即關閉鏈接?
由於,客戶機給服務器發送的確認響應有可能阻塞到網絡中,服務器收不到這個響應就不會關閉鏈接,客戶機若是沒有等待的話,客戶機關閉了,服務器就沒辦法關閉了,爲了保證雙方都可以無缺的關閉,這時候客戶機選擇再等待一段時間,若是客戶機給服務器的確認響應阻塞到網路中,那麼服務器等待超時以後會從新請求結束,客戶正好還沒關,就能夠再一次的回覆了,再回復一次給服務器,服務器這一次能收到了,就關閉了,客戶機再等待2MSL以後就能夠安心關閉了。