TCP是一個面向連接的傳輸層協議,因此不論哪一方需要傳輸數據,都需要在雙方之間建立一條傳輸連接。
用TCP的三次握手與四次揮手來解釋TCP的各個狀態之間的會比較清晰。
一、TCP的三次握手:
a) 單方主動發起連接:
1、 服務器端應用層的應用程序創建了一個socket,使服務端被動打開,從CLOSED狀態切換至LISTEN狀態;
2、 此時客戶端向服務端發送了一個SYN=1,seq=i的數據段,主動打開,并將狀態從CLOSED切換至SYN_SENT(此為TCP三次握手中的第一次握手);
3、 服務端收到客戶端的發來的同步請求后,給客戶端回應一個SYN=1,ACK=1,seq=j,ack=i+1的數據段,并將狀態從LISTEN切換至SYN_RCVD,等待客戶端的最后的ACK(此為TCP三次握手中的第二次握手);
4、 客戶端收到服務端發來的ACK與SYN請求后,回應服務端ACK=1,seq=i+1,ack=j+1數據段,并將狀態從SYN_SENT轉換至ESTABLISHED(此為TCP三次握手中的第三次握手);
5、 服務端收到客戶端發來的ACK確認后,將狀態從SYN_RCVD轉換至ESTABLISHED.
b) 雙方同時發起連接請求:
此種狀態并不存在一方為服務器,一方為客戶端的情況,主機A與主機B既是客戶端又是服務端。
1、 主機A與主機B同時向對方發起同步請求;并將狀態從CLOSED轉換到SYN_SENT
A:SYN=1 seq=i —–> B(在收到對方的SYN請求后,狀態從SYN_SENT轉換到SYN_RCVD)
B:SYN=1 seq=j —–> A(在收到對方的SYN請求后,狀態從SYN_SENT轉換到SYN_RCVD)
2、 主機A與主機B再同時確認對方的同步請求;
A:SYN=1 ACK=1 seq=i+1 ack=j+1 —–> B(在收到對方的ACK確認后,狀態從SYN_RCVD轉換到ESTABLISHED)
B:SYN=1 ACK=1 seq=j+1 ack=i+1 —–> A(在收到對方的ACK確認后,狀態從SYN_RCVD轉換到ESTABLISHED)
注:注意同時發起請求時各狀態轉換的時間
二、TCP的四次揮手:
a) 單方主動發起斷開請求:
1、 假設由客戶端主動發起斷開請求,客戶端向服務器端發送FIN=1,seq=m的數據段,請求斷開連接,并將狀態從ESTABLISHED轉換至FIN_WAIT 1 等待服務器確認;(此為四次揮手中的第一次揮手)
2、 服務器端接收到客戶端發來的FIN請求后,會回應給客戶端一個ACK=1
seq=n,ack=m+1的數據段,并將狀態從ESTABLISHED轉換至CLOSE_WAIT;此時如果服務器端還由未發送完成的數據,則會繼續發送;(此為四次揮手中的第二次揮手)
3、 客戶端收到來自服務器端發來的ACK數據段后,關閉客戶端至服務器方向TCP連接,此時整個TCP連接處于半關閉狀態(half-close);
客戶端狀態從FIN_WAIT 1切換至FIN_WAIT 2 ;等待服務器端發送FIN確認可以斷開連接;注:此時客戶端仍然可以接收來自服務器端發送的數據
4、 當服務器端數據傳輸完成,向客戶端發送FIN=1 ACK=1 seq=w ack=m+1的數據段(此時服務器ack確認的數據段為客戶端關閉TCP連接的最后一個數據段的序號),并將狀態從CLOSE_WAIT轉換至LAST_ACK,等待客戶端的ACK確認(此為TCP四次揮手的第3次揮手)
5、 客戶端收到來自服務器端發送的FIN數據段后,向服務器段發送ACK確認數據段,并將狀態從FIN_WAIT 2轉換至TIMED_WAIT;等待2MSL(最大報文段生存時間),如果沒有收到來自服務器端的回應,關閉TCP連接,從TIMED_WAIT狀態轉換至CLOSED狀態(此為TCP四次揮手的第四次揮手)
6、 服務器端在收到客戶端發送的ACK后,將狀態轉換為LISTEN;如果在一定時間內收不到客戶端的ACK,會重新向客戶端發送FIN數據段
b) 雙方同時發起FIN請求:
1、 雙方同時向對方發送FIN請求;并將狀態從ESTABLISHED轉換至FIN_WAIT 1
2、 雙方都收到來自對方發送的FIN請求時,將狀態從FIN_WAIT
1轉換至CLOSING;給對方發送ACK確認數據段后,又將狀態從CLOSING轉換至TIMED_WAIT;雙方在等待2MSL時長后,沒有收到來自對方的回應后,超時進入CLOSED狀態
c) 如果在客戶端向服務端發起SYN請求后,服務器段不愿意進行連接,此時服務器端會向客戶端發送一個FIN請求,并將狀態從SYN_RCVD切換到FIN_WAIT1;客戶端收到FIN后,會回應服務器端一個ACK數據段,表示雙方同時嘗試關閉連接;并將狀態從SYN_SENT切換至CLOSING;服務器端在收到客戶端發來的ACK數據段后,切換狀態至TIMED_WAIT;在超時后雙方即關閉連接。
三、各個狀態梳理:
CLOSED:初始狀態;
LISTEN:應用層應用程序創建了一個socket;
SYN_RCVD:收到SYN同步請求,回應對方發送ACK、SYN;
SYN_SENT:發送了SYN同步請求;
ESTABLSHED:收到了對方的ACK確認;
FIN_WAIT 1:發起了FIN終止連接的請求,還未得到對方確認;
CLOSE_WAIT:收到了對方的FIN請求,回應給對方ACK;
FIN_WAIT 2:發送FIN請求,收到了ACKA確認,但未收到對方的FIN請求;
LAST_ACK:向對方發送了FIN請求,還未得到確認;
TIMED_WAIT:收到對方的FIN請求,回應ACK,等待2MSL;
CLOSING:在向對方發送FIN后,先接到對方的FIN,從FIN_WAIT 1轉換至此狀態,在向對方發送ACK后會進入TIME_WAIT狀態;
原創文章,作者:M22-Zero,如若轉載,請注明出處:http://www.www58058.com/71378