1. TCP協議
1.1 TCP數據包頭
要了解三次握手和四次揮手,首先須要瞭解下TCP數據包頭的結構,以下: 服務器
- 源端口、目的端口:16位長,標識出遠端和本地的端口號;
- 序號:SEQ,32位長,標識發送的數據包的順序,防止數據包亂序;
- 確認號:32位長,接收方對發送方發送來的TCP報文段的響應,其值是對收到的報文序號加1,用於解決不丟包的問題;
- TCP頭長:4位頭長,標識tcp頭部能夠有多少個32bit,即多少個4字節,由於頭長是4位,最大能表示15,因此TCP頭部最大就是15*4等於60個字節,也就是說TCP包頭最長能夠有60個字節;
- URG:表示緊急指針是否有效;
- ACK:ACK位置1代表確認號是合法的,若是ACK爲0,那麼數據包不包含確認信息,確認字段被省略;
- PSH:提示接收端應用程序應該當即從TCP接收緩衝區中讀走數據,爲接收後續數據騰出空間;
- RST:表示要求對方從新創建鏈接,用於復位因爲主機崩潰或其餘緣由而出現的錯誤的鏈接,還能夠用於拒絕非法的數據報或拒絕鏈接請求;
- SYN:表示請求創建鏈接;
- FIN:表示通知對方要關閉鏈接了;
- 窗口大小:16位長,是一種流量控制的手段,這個窗口,指的是接收通告窗口,它告訴對端本端的TCP緩衝區還能容納多少字節的數據,這樣對方就能夠控制發送數據的速度;
- 校驗和:16位長,由發送端填充,接收端根據該值,校驗接收到的TCP報文段在傳輸過程當中是否損壞,校驗包括頭部和數據部分,它是TCP可靠傳輸的一個重要保障;
- 緊急指針:16位長,是一個正的偏移量,它和序號相加表示最後一個緊急數據的下一個字節的序號,確切的說,它是緊急指針相對當前序號的偏移,是發送端向接收端發送緊急數據的辦法;
- 可選項:TCP頭部最長能夠有60個字節,而前部分已知的字段佔用了20個字節,因此選項最多能夠有40個字節,包括最大TCP載荷,窗口比例、選擇重複數據報等選項;
注意:TCP數據包是沒有IP地址的,只有端口併發
1.2 三次握手協議
在利用TCP實現源主機和目的主機通訊時,目的主機必須贊成,不然TCP鏈接沒法創建。爲了確保TCP鏈接的成功創建,TCP採用了一種稱爲三次握手的方式,三次握手方式使得「序號/確認號」系統可以正常工做,從而使它們的序號達成同步。若是三次握手成功,則鏈接創建成功,能夠開始傳送數據信息。 三次握手:爲應用程序提供可靠的通訊鏈接,適合於一次傳輸大批數據的狀況,並適用於要求獲得響應的應用程序。 其三次握手分別爲:socket
- 源主機A的TCP向主機B發送鏈接請求報文段,其首部中的SYN(同步)標誌位應置爲1,表示想跟目標主機B創建鏈接,進行通訊,併發送一個同步序列號X(例:SEQ=100)進行同步,代表在後面傳送數據時的第一個數據字節的序號爲X+1(即101), 此時client端狀態爲SYN_SENT。
- 目標主機B的TCP收到鏈接請求報文段後,如贊成,則發回確認。再確認報中應將ACK位置爲1.確認號爲X+1,同時又向A也發送一個SYN=1,併發送一個序號Y, 此時server端狀態爲SYN_RCVD。
- 源主機A的TCP收到目標主機B的確認後要想目標主機B給出確認。其ACK置爲1,確認號爲Y+1,而本身的序號爲X+1。TCP的標準規定,SYN置1的報文段要消耗掉一個序號, 當兩邊都確認完成後,狀態改成ESTABLISHED。
運行客戶進程的源主機A的TCP通知上層應用進程,鏈接已經創建。 當源主機A向目標主機B發送第一個數據報文段時,其序號仍爲X+1,由於前一個確認報文段並不消耗序號。 當運行服務進程的目標主機B的TCP收到源主機A的確認後,也通知其上層應用進程,鏈接已經創建。至此創建了一個全雙工的鏈接。tcp
1.3 tcp斷開鏈接四次揮手
tcp創建鏈接是三次,但斷開鏈接卻要四次,是由於tcp是全雙工的,兩個方向上都須要進行關閉。3d
- 當主機A完成數據傳輸後,將控制位FIN置1,向主機B提出中止TCP鏈接的請求,狀態改成FIN_WAIT_1,此時,該數據包中,序列號爲主機B發送的上一個數據包中的確認號值,而確認號爲主機A發送的上一個數據包中的序列號+該數據包所帶的數據的大小;
- 主機B收到FIN後對其做出響應,確認這一方向上的TCP鏈接將關閉,將ACK置1,此時服務器狀態改成CLOSE_WAIT, 客戶端狀態改成FIN_WAIT_1,此時序列號爲上一步中的確認號,確認號爲上一步中的序列號加1;
- 由B 端再提出反方向的關閉請求,將FIN置1,服務端狀態爲LAST_ACK,客戶端狀態爲TIME_WAIT,此時序列號爲上一步的確認號,確認號爲上一步的序列號加上數據包所帶數據的大小;
- 主機A對主機B的請求進行確認,將ACK置1,雙方向的關閉結束狀態爲CLOSED,此時序列號爲上一步中的確認號,確認號爲上一步中的序列號加1;
注意 : FIN和SYN同樣,也要消耗一個序號。理論上服務器在TCP鏈接關閉時發送的終止數據包中,只有終止位置是1,而後客戶端進行確認。可是在實際的 TCP實現中,在終止數據包中,確認位和終止位是同時置爲1的,確認位置爲1表示對最後一次傳輸的數據進行確認,終止位置爲1表示關閉該方向的TCP連 接。指針
1.4 TCP有哪些狀態
通常咱們可使用netstat查看當前socket狀態。cdn
- CLOSED:表示初始狀態;
- LISTEN:表示服務器端的某個socket處於監聽狀態,能夠接受鏈接;
- SYN_SENT:三次握手時,客戶端發送第一次SYN鏈接請求後,狀態SYN_SENT;
- SYN_RCVD:也是三次握手時服務端的一箇中間狀態;
- ESTABLISHED:表示鏈接已經創建,這裏要說明一下,其實TCP鏈接並非真的有什麼東西連着在,只是說雙方都是ESTABLLISHED狀態,就說明雙方鏈接正常;
- FIN_WAIT_1:已經創建鏈接後,其中一方請求終止鏈接,四次揮手中間狀態;
- TIME_WAIT:表示收到了對方的FIN報文,併發送出了ACK報文,就等2MSL(默認是2min)後回到CLOSED可用狀態;
- CLOSING:表示發送FIN報文後,沒有收到對方的ACK報文,反而收到了對方的FIN報文,這種狀況其實就是雙方同時關閉socket;
- CLOSE_WAIT:四次揮手中間狀態,表示在等待關閉鏈接;
- LAST_ACK:四次揮手時被動關閉一方在發送FIN報文後,等待對方的ACK確認報文;
- RST:同時打開和同時關閉;
1.5 TIME_WAIT爲何要等2MSL纔會變爲CLOSED
有兩個緣由:server
- 可靠地終止TCP鏈接,在四次揮手的最後一步中,可能客戶端發送到服務端的確認包丟失,服務端就會重發結束報文段,客戶端從新發起確認報文段,而這就須要停留一段時間;
- 保證讓遲來的TCP報文段有足夠的時間被識別並丟棄,若是沒有停留一段時間,原來客戶端的端口號就能夠當即被另一個應用程序重用,此時若是服務端有遲來的報文段,就會發到該新的應用程序上去,而這顯然是不被容許的;
注意:報文段的生存週期是一個MSL,因此在2MSL後,不會還存在遲到的報文段。blog
原文首發自簡書:www.jianshu.com/p/293d4ca66…進程