目錄
1.TCP協議段格式。
2.TCP協議傳輸時候的性質。
2.1確認應答。
2.2超時重傳。
2.3連接管理。
2.3.1 三次握手。
2.3.2四次揮手。
3.TCP常見的狀態。
?
1.TCP協議段格式。
TCP協議段是由首部和數據兩部分構成的。首部包含了TCP通信所需要的各種控制信息,而數據部分則是實際要傳輸的應用層數據。
下面小編通過圖片給大家進行描述:
?
?下面解釋下上述協議段里面各部分的含義(下述所說的長度都是以比特為單位):
1.源端口號:16位。用于標識發送方應用程序使用的端口號。2.目的端口號:16位。用于標識接收方應用程序使用的端口號。
3.序列號:32位。對字節流進行編號,用于保證數據的有序傳輸和檢測數據丟失。第一個自己的序列號由發送方隨機生成。
4.確認序列號:32位。接收方期望收到發送方下一個報文段的第一個數據字節的序列號。用于確認數據是否傳輸成功。
5.數據偏移:4位。表示該TCP頭部有多少個32位bit(4字節為單位)
?6.保留位:6位。當前先保留著,防止后面要使用。
7.控制位:6位。
URG:緊急指針有效標志。
ACK:確認號是否有效。
PSH:提示接收方應盡快將數據交付給應用層。
RST:重置連接標志。
SYN:同步序列號標志,用于建立連接,我們把攜帶SYN標識的稱為同步報?段。
FIN:結束標志,用于關閉連接,我們稱攜帶FIN標識的為結束報?段。
8.窗口大小:16位。表示發送方的接受窗口大小,用于流量控制。
9.校驗和:16位。對傳輸的數據進行傳輸前后計算并進行對比,確保數據傳輸的完整性。
10.緊急指針:16位。當URG標志置為1時有效,指出緊急數據的末尾在報文段中的位置。
11.選項:可變。提供額外的功能,如:最大報文段長度,窗口擴大因子等。
2.TCP協議傳輸時候的性質。
2.1確認應答。
?我們觀察下面的圖:
我們每次從一個主機上面傳輸信息傳給另外一個主機的時候,我們會先傳輸一次,之后接收方會給發送方返回自己收到了,并且下一次傳輸從哪里開始。
2.2超時重傳。
?我們觀察下面的圖片:
圖1:
我們觀察圖一,發現我們丟包的現象是在傳輸數據的時候丟失的,我們的TCP對等待一定自己設置的時間,要是發送方還是沒有接受到接受方所返回的確認應答操作,就會讓主機1再次發送信息,重新進行操作。
但是我們觀察上述的流程,我們會發現還有一種可能,是應為確認應答沒有返回回來。
圖2:
上述圖片展示的就是我們的第二種可能,是在接受方傳輸確認應答的時候,出現了問題。
我們會發現主機2會接收到重復的信息,TCP協議就會給我們識別出來重復的信息,之后將重復的丟棄掉。我們就通過我們前面所提到的序列號進行解決,很容易就達到去重的效果。
那么還有一個問題值得我們考慮,就是我們中間等待的時間?
我們等待的時間就是我們 單趟路程*2 的總時間,但是在實際情況中,TCP為了保證無論在任何環境下都能比較?性能的通信, 因此會動態計算這個最?超時時間。
2.3連接管理。
在連接管理的階段,TCP會進行三次握手建立連接和四次揮手斷開連接,我們的的連接管理是虛擬的,只保存雙方關鍵的信息。
2.3.1 三次握手。
下面我先通過TCP在代碼中的運行過程給大家說明下:
我們觀察上述的圖片,我們可以輕易的看到客戶端給服務器先發送了一次信息,之后服務器給客戶端發送了兩次信息,最后客戶端給服務器再次發送了一條信息。
可能會有同學提出疑問,上述圖片中我們明明傳輸了四次,為什么說的是三次握手?
之所以我們說的是三次握手,是因為我們中間的兩次服務器給客戶端發消息的過程,可以合并為一處,之所以可以合并為一處是因為SYN和ACK是內核控制的,和代碼沒有沒有關系,所以可以合并。
這里呢我們進行的三次握手,是是能由客戶端發起的。
握手的意義:
1.驗證鏈路是否暢通。
2.發送和接受能力是否正常。
3.讓通信雙方協商關鍵信息。
我們所進行的握手和生活中是一樣的。例子:當我們長時間不回家的話,我們過年回家的時候就會很大可能碰到我們的老朋友,我們見面了指定會進行一下寒暄的,當然了我們也是會進行握手的,我們進行握手就好比我們進行了雙方信息的確認。還有就是為啥要進行驗證鏈路是否正常,因為我們只有正常的話才會可能進行信息的正確傳遞。例子:相比大家都做過地鐵,我們每天早上進行的第一趟地鐵運行的話,都會進行一趟空車的跑動,就是為了防止后面要是在載著一車的顧客的情況下出現問題,我們跑一趟之后就知道是否可以正常運行,這樣我們后面就可以進行及時的修改。
2.3.2四次揮手。
我們進行揮手的最終目的就是為了釋放沒有再運行的空間。
圖片:
我們觀察上圖,大家可能觀察到和之前的三次握手好像沒有什么區別,無非就是將每次進行的控制位進行了更改,那這為什么就成了四次揮手了呢!
大家觀察前面的三次握手,是因為中間的兩次是可以進行合并的,那這叫做四次揮手,就是中間的兩次不會每次都能進行合并。我們要想夠清楚為什么是不一定能夠進行合并的原因是什么?那是因為我們最后在進行揮手的時候進行的是Fin,這個主要是由我們在程序里面的代碼進行控制的——close() ,當我們在主程序執行完了之后再finally里面,close()前面有大片的代碼需要進行執行的時候,就會記性長時間的等待,所以中間兩次的ACK(確認信息)首先進行返回,最后后面的Fin在記性返回,這就將中間的兩次進行了分離。
前面我們說了我們為什么不能進行合并的原因,那么我們要是能進行合并的時候,辦法也是非常顯而易見的,就是Fin觸發close()之間的時間是本身不長的并且ACK可以往后面拖一段時間,這樣我們就可以將中間的兩次進行合并,這就是我們的四次揮手。
3.TCP常見的狀態。
1.CLOSE:默認狀態。這是TCP連接的最初和最終的狀態,意味著沒有任何連接的存在。在JAVA里,當SOCKET對象還沒有進行創建的時候,或者連接關閉的時候,就處于該狀態。
2.LISTEN:隨時可以進行連接。
3.ESTABLISHED:客戶端和服務器的連接已經建立好。客戶端收到服務器的SYN+ACK報文后,發送ACK報文,之后客戶端和服務端都進入ESTABLISHED 狀態,此時TCP連接成功建立,雙方可以進行數據傳輸。在JAVA里面,當SOCKET連接成功后,就處于該狀態。
4.CLOSE_WAIT:被動斷開連接的一方的狀態。接受Fin 報文的乙方接收到 Fin 報文后,發送 ACK 報文,然后進入?CLOSE_WAIT 狀態。此時是關閉等待狀態,需要調用close() 方法進行關閉連接,發送FIN 報文。
5.TIME_WAIT:等待連接徹底釋放。發送 FIN 報文的一方收到對方的 ACK 報文后,進入 TIME_WAIT 狀態,等待一段時間后,才會進入 CLOSED 狀態。中間的等待時間是為了最后一個ACK 報文能夠到達到達對方。