咱們對TCP三次握手耳熟能詳,那麼你知道TCP四次揮手過程嗎?bash
1、前言
唐代詩人李商隱在《無題》詩中寫到:「相見時難別亦難,東風無力百花殘」,表達了本身與心愛之人相見之難、離別之苦。若是把這句詩用在形容TCP鏈接的創建與釋放過程,也很貼切。咱們知道TCP創建鏈接時須要三次握手,而TCP鏈接釋放則須要四次揮手,是否是很像詩中描述的意境——見面很難,分開更難。 若是你還不清楚相見之難—TCP三次握手過程,能夠看個人上篇博文TCP三次握手原理,這樣便於你更好理解TCP四次揮手釋放鏈接的過程。網絡
2、TCP四次揮手過程
TCP四次揮手指的是TCP鏈接釋放過程, 不一樣於TCP鏈接創建時的三次握手過程,TCP鏈接釋放過程更加複雜。在進入正題前,咱們先回憶下TCP協議的兩個重要特色:post
- TCP協議面向鏈接:應用在使用TCP協議通信時,必需要先創建TCP鏈接。
- TCP鏈接是雙向通訊:通訊的兩端是對等的,既能發送數據,也能接收數據,就向咱們打電話時同樣,既能說也能聽。
這兩個重要特色決定了TCP鏈接的釋放過程。下面咱們一塊兒來看下TCP四次揮手的過程都發生了什麼。爲了更好的理解,簡單的畫了下TCP四次揮手示意圖以下: spa
TCP鏈接
數據傳輸結束後,通訊的雙方client與server均可以選擇釋放當前TCP鏈接,此時client與server都處於
ESTABLISHED(鏈接確立)狀態,TCP鏈接釋放今後狀態開始,咱們假設是client的應用進程主動發起TCP鏈接釋放:
- 第一次揮手:client向server主動發送鏈接釋放報文(FIN=1,seq=u),報文的首部控制位FIN=1,表明本身的數據已經發送完畢,而且要求釋放TCP鏈接。序號seq=u,u的值爲client前面已傳送數據的最後一個字節序號加1,client發送完後進入FIN-WAIT-1(終止等待1)狀態。
- 第二次揮手:server收到client的鏈接釋放報文後即給出確認報文(ACK=1,ack=u+1,seq=v),序號seq=v,值爲server前面已傳送數據的最後一個字節序號加1,而後server進入CLOSE-WAIT(關閉等待)狀態。==這時候client到server這個方向鏈接就釋放了,TCP鏈接處於 半關閉(half-close)狀態==,client再也不發送數據,可是server仍然能夠發送數據給client。 client收到server確認後進入FIN-WAIT-2(終止等待2)狀態,而後等待server發出鏈接釋放報文
- 第三次揮手:處於CLOSE-WAIT狀態的server發送完全部數據後,主動釋放鏈接,server發送的鏈接釋放報文(FIN=1,ACK=1,seq=W,ack=u+1),由於半關閉狀態,server可能又發送了一些數據,因此序號的值爲W,同時保持確認號ack=U+1與上次一致,發送完畢後,server進入LAST-ACK(最後確認)狀態,等待client確認。
- 第四次揮手:client收到server鏈接釋放報文後,給出確認報文(ACK=1,ack=w+1,seq=u+1),此時鏈接還沒釋放掉,client要時間等待計時器設置的2MSL的時間,才最終進入CLOSED狀態。時間MSL是最長報文壽命時長,RFC793建議爲2分鐘,可是如今網絡中,這個時間設置更小。也就是說client要等待4分鐘才能進入CLOSED狀態,開始下一個鏈接。
上面就是TCP鏈接的釋放過程,若是你以爲比較複雜能夠簡單理解爲這樣:3d
client——> server: 數據傳輸完畢,請求釋放鏈接!
server——> client: 收到,能夠釋放鏈接!等我處理完畢會通知你
server——> client: 個人數據也發送完畢!能夠釋放鏈接
client——>server: 收到!已釋放鏈接,Bye
複製代碼
3、小細節
1.爲何client在TIME-WAIT狀態必須等待2MSL的時間?
- 爲了保證client的最後發送的ACK報文能到達server。由於這個ACK報文可能丟失,致使處於LAST-ACK狀態的server收不到對本身釋放鏈接報文的確認。如果server超時重傳了這個報文,client就能在2MSL時間內收到,而且從新一次確認,並重啓2MSL計時器。
- 防止出現「已失效的鏈接請求報文段」出現,2MSL時間,可使本鏈接持續時間內的報文段都從網絡中消失。創建下一個TCP鏈接時就不會出現上次舊鏈接請求報文段
2.若是一方忽然出故障了怎麼辦?
在TCP鏈接創建後,client與server傳輸過程當中,假設client忽然出故障了,server顯然沒法再收到client數據了,可是server不能白白等下去。這時TCP的保活計時器(keepalive timer)就登場了。server每收到一次client的數據,就從新設置一下計時器,時間一般是2小時,若2小時內沒有再收到client數據,server就會發送一次探測報文段,之後每隔75分鐘發送一次,若一連發送10次,client都沒有任何響應,server會認爲client故障了,直接關閉鏈接。 code
4、總結
爲了更清晰看到TCP各類鏈接之間關係,最後附上一張TCP有限狀態機圖: cdn