這裏主要記錄在平常中對知識的學習,經過結合筆記與自身理解的方式嘗試寫下總結
文章對細節可能不會一一介紹解釋,內容僅做參考
複製代碼
前段時間看了HTTP相關的知識,但感受還有還多細節面沒有了解到位。此次補充與TCP鏈接有關的服務器
1、頭部字段
一些須要前置瞭解的知識點網絡
- Sequence number 順序號碼:保證TCP傳輸的報文都是有序的
- Acknowledge number 確認號碼:表示數據接收端指望接收的下一個字節的編號是多少,並表示上一個序號已接收完成
- 確認方Ack = 發起方Req+1,兩端配對
- Window Size 窗口大小:表示還能接收多少字節的數據,用於流量控制
- RTT:表示發送端發送數據到接收到對端數據所需的往返時間
標識符:學習
- URG=1: 表示本數據報的數據部分包含緊急信息,是一個高優先級數據報文,此時緊急指針有效。緊急數據必定位於當前數據報數據部分的最前面,緊急指針標明瞭緊急數據的尾部
- ACK=1: 表示確認字段有效。TCP還規定在鏈接創建後傳送的全部報文段都必須把ACK置爲1
- PSH=1: 表示接收端應該當即將數據push給應用層,而不是等到緩衝區滿後再提交
- RST=1: 表示當前TCP鏈接出現嚴重問題,可能須要從新創建TCP鏈接,也可能用於拒絕非法的報文段和拒絕鏈接請求
- SYN=1: 當SYN=1,ACK=0時,表示當前報文段是一個鏈接請求報文;當SYN=1,ACK=1時,表示當前報文段是一個贊成創建鏈接的應答報文
- FIN=1: 表示此報文段是一個釋放鏈接的請求報文
2、三次握手
在TCP協議中,主動發起請求的一端爲客戶端,被動鏈接的一端爲服務端。不論是客戶端仍是服務端,TCP鏈接創建完成後都能發送和接收數據,因此TCP是一個全雙工的協議spa
一次TCP的創建須要進行三次對話,從而肯定一個鏈接,進而開始通信3d
過程如圖所示:指針
- 第一次握手:客戶端向服務端發送連接請求報文段。該報文段中包含自身的數據通信初始序號Seq=X和鏈接請求SYN。請求發送後,客戶端進入SYN-SENT狀態
- 第二次握手:服務端收到連接請求報文段後,若是贊成鏈接,則會發送一個包含自身的數據通信初始序號Seq=Y、確認序號Ack=X+1和應答標識ACK的確認應答。發送完成後,服務端進入SYN-RECEIVED狀態
- 第三次握手:當客戶端收到鏈接贊成的應答後,還要向服務端發送一個確認報文(Ack=Y+1,Seq=Z,ACK)。客戶端發完這個報文段後進入ESTABLISHED狀態,此時鏈接創建成功
明明兩次握手就能夠創建鏈接,爲何還須要第三次應答呢:code
由於這是爲了防止失效的鏈接請求報文段被服務端接收,從而產生錯誤cdn
若是是這樣:客戶端發送了一個鏈接請求A,可是由於網絡緣由形成了超時,這時TCP會啓動超時重傳的機制再發送一個鏈接請求B。此時請求B順利到達服務端,服務端應答完成就創建鏈接。若是鏈接請求A在兩端關閉後終於到達了服務端,那麼這時服務端會認爲客戶端又須要創建TCP鏈接從而應答後進入ESTABLISHED狀態。此時客戶端實際上是CLOSED狀態,那麼就會致使服務端一直等待,形成資源浪費blog
在創建鏈接中,任意一端掉線,TCP都會重發SYN包,通常會重試5次,在創建鏈接中可能會遇到SYN FLOOD攻擊,能夠選擇調低重試次數或乾脆在不能處理的狀況下拒絕請求資源
3、四次揮手
TCP是全雙工的,在斷開鏈接時兩端都須要發送FIN斷開請求和ACK確認
過程如圖所示:
- 第一次揮手:客戶端認爲數據發送完成,向服務端發送鏈接釋放請求
- 第二次揮手:服務端收到鏈接釋放請求,會告訴應用層要釋放TCP鏈接。而後發送確認應答,並進入CLOSE_WAIT狀態,表示客戶端到服務端的鏈接已經釋放,不接收客戶端發的數據了。可是由於TCP鏈接是雙向的,因此服務端仍舊能夠發送數據給客戶端
- 第三次揮手:若是此時服務端還有沒有發完的數據,會繼續發送。等到發送完畢後會向客戶端發送鏈接釋放請求,並進入LAST-ACK狀態
- 第四次揮手:客戶端收到釋放請求後,會向服務端發送確認應答。此時客戶端進入TIME-WAIT狀態,會持續2MSL(最大段生存期,指報文段在網絡中生存的時間,超時會被拋棄),若該時間段內沒有服務器的重發請求的話,就進入CLOSED狀態。當服務端收到確認應答的時候,也進入了CLOSED狀態
爲何客戶端要進入TIME-WAIT狀態,等待2MSL後才進入CLOSED狀態呢:
爲了保證服務端能收到客戶端的確認應答。若客戶端發完確認應答後直接進入CLOSED狀態,若是確認應答由於網絡問題一直沒有到達,那麼會形成服務端不能正常關閉
爲何鏈接的時候是三次握手,關閉的時候倒是四次握手:
由於當服務端收到客戶端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當服務端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴客戶端,"你發的FIN報文我收到了"。只有等到我服務端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手