本篇轉載自掘金:https://juejin.im/post/5b29d2...服務器
TCP 三次握手就比如兩我的在街上隔着50米看見了對方,可是由於霧霾等緣由不能100%確認,因此要經過招手的方式相互肯定對方是否定識本身。
網絡
張三首先向李四招手(syn),李四看到張三向本身招手後,向對方點了點頭擠出了一個微笑(ack)。張三看到李四微笑後確認了李四成功辨認出了本身(進入estalished狀態)。tcp
可是李四還有點狐疑,向四周看了一看,有沒有可能張三是在看別人呢,他也須要確認一下。因此李四也向張三招了招手(syn),張三看到李四向本身招手後知道對方是在尋求本身的確認,因而也點了點頭擠出了微笑(ack),李四看到對方的微笑後確認了張三就是在向本身打招呼(進入established狀態)。post
因而兩人加快步伐,走到了一塊兒,相互擁抱。學習
咱們看到這個過程當中一共是四個動做,張三招手--李四點頭微笑--李四招手--張三點頭微笑。其中李四連續進行了2個動做,先是點頭微笑(回覆對方),而後再次招手(尋求確認),實際上能夠將這兩個動做合一,招手的同時點頭和微笑(syn+ack)。因而四個動做就簡化成了三個動做,張三招手--李四點頭微笑並招手--張三點頭微笑。這就是三次握手的本質,中間的一次動做是兩個動做的合併。spa
咱們看到有兩個中間狀態,syn_sent和syn_rcvd,這兩個狀態叫着「半打開」狀態,就是向對方招手了,可是還沒來得及看到對方的點頭微笑。syn_sent是主動打開方的「半打開」狀態,syn_rcvd是被動打開方的「半打開」狀態。客戶端是主動打開方,服務器是被動打開方。操作系統
TCP 數據傳輸就是兩我的隔空對話,差了一點距離,因此須要對方反覆確認聽見了本身的話。code
張三喊了一句話(data),李四聽見了以後要向張三回覆本身聽見了(ack)。排序
若是張三喊了一句,半天沒聽到李四回覆,張三就認爲本身的話被大風吹走了,李四沒聽見,因此須要從新喊話,這就是tcp重傳。資源
也有多是李四聽到了張三的話,可是李四向張三的回覆被大風吹走了,以致於張三沒聽見李四的回覆。張三並不能判斷到底是本身的話被大風吹走了仍是李四的回覆被大風吹走了,張三也不用管,重傳一下就是。
既然會重傳,李四就有可能同一句話聽見了兩次,這就是「去重」。「重傳」和「去重」工做操做系統的網絡內核模塊都已經幫咱們處理好了,用戶層是不用關心的。
張三能夠向李四喊話,一樣李四也能夠向張三喊話,由於tcp連接是「雙工的」,雙方均可以主動發起數據傳輸。不過不管是哪方喊話,都須要收到對方的確認才能認爲對方收到了本身的喊話。
張三多是個高射炮,一說連說了八句話,這時候李四能夠不用一句一句回覆,而是連續聽了這八句話以後,一塊兒向對方回覆說前面你說的八句話我都聽見了,這就是批量ack。可是張三也不能一次性說了太多話,李四的腦子短期可能沒法消化太多,兩人之間須要有協商好的合適的發送和接受速率,這個就是「TCP窗口大小」。
網絡環境的數據交互同人類之間的對話還要複雜一些,它存在數據包亂序的現象。同一個來源發出來的不一樣數據包在「網際路由」上可能會走過不一樣的路徑,最終達到同一個地方時,順序就不同了。操做系統的網絡內核模塊會負責對數據包進行排序,到用戶層時順序就已經徹底一致了。
TCP斷開連接的過程和創建連接的過程比較相似,只不過中間的兩部並不老是會合成一步走,因此它分紅了4個動做,張三揮手(fin)——李四傷感地微笑(ack)——李四揮手(fin)——張三傷感地微笑(ack)。
之因此中間的兩個動做沒有合併,是由於tcp存在「半關閉」狀態,也就是單向關閉。張三已經揮了手,但是人尚未走,只是再也不說話,可是耳朵仍是能夠繼續聽,李四呢繼續喊話。等待李四累了,也再也不說話了,朝張三揮了揮手,張三傷感地微笑了一下,才完全結束了。
上面有一個很是特殊的狀態time_wait
,它是主動關閉的一方在回覆完對方的揮手後進入的一個長期狀態,這個狀態標準的持續時間是4分鐘,4分鐘後纔會進入到closed狀態,釋放套接字資源。不過在具體實現上這個時間是能夠調整的。
它就比如主動分手方要承擔的責任,是你提出的要分手,你得付出代價。這個後果就是持續4分鐘的time_wait
狀態,不能釋放套接字資源(端口),就比如守寡期,這段時間內套接字資源(端口)不得回收利用。
它的做用是重傳最後一個ack報文,確保對方能夠收到。由於若是對方沒有收到ack的話,會重傳fin報文,處於time_wait狀態的套接字會當即向對方重發ack報文。
同時在這段時間內,該連接在對話期間於網際路由上產生的殘留報文(由於路徑過於崎嶇,數據報文走的時間太長,重傳的報文都收到了,原始報文還在路上)傳過來時,都會被當即丟棄掉。4分鐘的時間足以使得這些殘留報文完全消逝。否則當新的端口被重複利用時,這些殘留報文可能會干擾新的連接。
4分鐘就是2個MSL,每一個MSL是2分鐘。MSL就是maximium segment lifetime
——最長報文壽命。這個時間是由官方RFC協議規定的。至於爲何是2個MSL而不是1個MSL,我尚未看到一個很是滿意的解釋。
四次揮手也並不老是四次揮手,中間的兩個動做有時候是能夠合併一塊兒進行的,這個時候就成了三次揮手,主動關閉方就會從fin_wait_1
狀態直接進入到time_wait
狀態,跳過了fin_wait_2
狀態。
TCP狀態轉換是一個很是複雜的過程,本文僅對一些簡單的基礎知識點進行了類比講解。關於TCP的更多知識還須要讀者去搜尋相關技術文章進入深刻學習。若是讀者對TCP的基礎知識掌握得比較牢固,高級的知識理解起來就不會太過於吃力。