一 TCP:傳輸控制協議報文格式
1 TCP服務
-
提供面向連接、可靠的字節流服務
-
面向連接意味着兩方通信,不支持多播和廣播
-
可靠性的支持:
- 應用數據被分割成TCP認為最適合發送的數據塊。由TCP傳遞給IP的信息單位稱為報文段或段(segment)。
- 當TCP發出一個段后,它啟動一個定時器,等待目的端確認收到這個報文段。如果不能及時收到一個確認,將重發這個報文段。
- 當TCP收到發自TCP連接另一端的數據,它將響應一個確認。
- TCP將保持它首部和數據的檢驗和。
- TCP將對收到的數據進行重新排序,將收到的數據以正確的順序交給應用層。
- IP數據報會發生重復,TCP的接收端必須丟棄重復的數據。
- TCP還能提供流量控制,TCP連接的每一方都有固定大小的緩沖空間,防止較快主機致使較慢主機的緩沖區溢出。
- TCP對字節流的內容不作任何解釋。對字節流的解釋由TCP連接雙方的應用層解釋。
2 TCP首部
- TCP首部為20個字節
- 源端口號和目的端口號 :4個字節,用於尋找發端與收端的應用進程。
- 32位序號:4個字節,用於識別從TCP發端向收端發送的數據字節流,循環利用,逐個遞增。
- 32位確認序號:4個字節,上次已成功收到數據字節序號加1(只有在ACK標志為1時,該字段才有效)
- 首部長度:4位,用於標識首部的長度,即為5 * 4~15 * 4字節等於20~60字節(固定報頭(20字節) + 可選選項)
- 標志比特:
- URG:緊急指針
- ACK:確認序號有效
- PSH:接受方應盡快將報文段交給應用層
- RST:重建連接
- SYN:同步序號用來發起一個連接
- FIN:發端完成發送任務
- 窗口大小:用於流量控制,最大為65535字節(16位)
- 檢驗和:覆蓋整個TCP報文段(TCP首部和數據),發端計算和存儲,收端驗證
- 緊急指針:當URG為1時,才有效。
二 TCP連接的建立與終止
1 連接的建立與終止
(1)建立連接協議(三次握手連接)
- Client發送SYN段指明打算連接Serer的端口以及初始序號(ISN),SYN為1
- Server響應Server的初始序號(ISN)作為應答,同時將確認序號設置為Client的ISN+1以對Client的SYN報文進行確認。
- Client將確認序號設置為Server的ISN+1以對Server的SYN報文進行確認。
(2)WireShark抓包分析三次握手連接
# client的SYN報文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 0, Len: 0
Source Port: 1682 # 源端口
Destination Port: 1883 # 目標端口
Sequence number: 0 (relative sequence number) # 序號
Acknowledgment number: 0 # 確認序號
1000 .... = Header Length: 32 bytes (8) # 首部長度
Flags: 0x002 (SYN) # 標識符
Window size value: 64240 # 窗口大小
Checksum: 0xa6f3 [unverified] # 檢驗和
Urgent pointer: 0 # 由於URG為0,所以緊急指針為0
Options: (12 bytes), Maximum segment size, No-Operation (NOP), Window scale, No-Operation (NOP), No-Operation (NOP), SACK permitted # 可選選項,后續講解
TCP Option - Maximum segment size: 1460 bytes # 最大報文端長度
TCP Option - No-Operation (NOP) # 無操作
TCP Option - Window scale: 8 (multiply by 256) # 窗口擴大因子
TCP Option - No-Operation (NOP)
TCP Option - No-Operation (NOP)
TCP Option - SACK permitted
# server的響應報文和SYN報文
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 0, Ack: 1, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 0 (relative sequence number)
Acknowledgment number: 1 (relative ack number) # client的Squence number plus one
1000 .... = Header Length: 32 bytes (8)
Flags: 0x012 (SYN, ACK) # 設置SYN和ACK(響應)
Window size value: 14600
Checksum: 0xfd7c [unverified]
Urgent pointer: 0
Options: (12 bytes), Maximum segment size, No-Operation (NOP), No-Operation (NOP), SACK permitted, No-Operation (NOP), Window scale
TCP Option - Maximum segment size: 1412 bytes
TCP Option - No-Operation (NOP)
TCP Option - No-Operation (NOP)
TCP Option - SACK permitted
TCP Option - No-Operation (NOP)
TCP Option - Window scale: 6 (multiply by 64)
# client的響應報文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 1, Ack: 1, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 1 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x010 (ACK)
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0
(3)連接終止協議
- Client發送FIN報文,此時Client不再發送業務數據到Server,並等待Server的響應報文(Client應用程序關閉)
- Server收到Client的報文,響應ACK報文。
- Server發送FIN報文,此時雙方都不再發送業務數據數據,並等待Client的響應報文(Server應用程序關閉))
- Server收到Client的ACK報文即終止連接。
(4)WireShark抓包分析正常關閉
# Client發送FIN報文
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 3, Ack: 1, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 3 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK) # ACK是由於需要響應先前的交互
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0
# Server發送ACK
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 1, Ack: 4, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 1 (relative sequence number)
Acknowledgment number: 4 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK)
Window size value: 229
Checksum: 0x759f [unverified]
Urgent pointer: 0
# Server發送FIN
Transmission Control Protocol, Src Port: 1883, Dst Port: 1682, Seq: 1, Ack: 4, Len: 0
Source Port: 1883
Destination Port: 1682
Sequence number: 1 (relative sequence number)
Acknowledgment number: 4 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x011 (FIN, ACK)
Window size value: 229
Checksum: 0x759f [unverified]
Urgent pointer: 0
# Client發送ACK
Transmission Control Protocol, Src Port: 1682, Dst Port: 1883, Seq: 4, Ack: 2, Len: 0
Source Port: 1682
Destination Port: 1883
Sequence number: 4 (relative sequence number)
Acknowledgment number: 2 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x010 (ACK)
Window size value: 259
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0
2 連接建立的超時重試
- 第一次超時
- 6秒后重試
- 24秒后重試
- ......
- 非固定,可調整
3 最大報文段長度:MSS
- 最大報文長度(MSS)表示TCP傳往另一端的最大塊數據的長度。
- 默認536字節,超出需要分節(Segment),該值來源於IPv4的最小重組緩沖區大小(576字節),IP首部+TCP首部為40字節,所以傳輸數據為576-40=536字節。
4 TCP的半關閉
- TCP提供了連接的一端在結束它的發送后還能接受來自另一端數據的能力。
- 即我已經完成了數據傳送,因此發送一個文件結束(FIN)給另一端,但我還想接收另一端發來的數據,直到它給我發來文件結束(FIN)
5 復位報文段:RST
(1)發到不存在的端口的連接請求
(2)異常終止一個連接
# 某一端直接關閉連接
Transmission Control Protocol, Src Port: 2446, Dst Port: 1883, Seq: 1, Ack: 1, Len: 0
Source Port: 2446
Destination Port: 1883
Sequence number: 1 (relative sequence number)
Acknowledgment number: 1 (relative ack number)
0101 .... = Header Length: 20 bytes (5)
Flags: 0x014 (RST, ACK) # 復位報文
Window size value: 0
Checksum: 0xa6e7 [unverified]
Urgent pointer: 0
- 優點
- 應用程序丟棄任何代發的數據並立即發送復位報文段
- RST的接收方會區分另一端執行的是異常關閉還是正常關閉
(3)檢測半打開連接
- 半打開:一方終止,一方還不知道。
- 出現原因:掉電(模擬機直接關閉即可)
6 同時打開
- 雙方同時執行主動打開,即每一方都發送SYN,但最終只建立了一個連接。
- 模擬這個可以通過辣雞VPN進行測試,如亞馬遜的免費雲(即往返時間比較長,便於模擬)。
7 同時關閉
- 同時關閉與正常關閉使用的段交換數目相同。
8 TCP選項
- 選項表結束:kind=0(1字節)
- 無操作:kind=1(1字節)
- 最大報文長度:kind=2(1字節),len=4(1字節),最大報文段長度(2字節)
- 窗口擴大因子:kind=3(1字節),len=3(1字節),移位數(1字節)
- 時間戳:kind=8(1字節),len=10(1字節),時間戳值(4字節),時間戳回顯應答(4字節)
# 發送MSS
TCP Option - Maximum segment size: 1460 bytes
Kind: Maximum Segment Size (2)
Length: 4
MSS Value: 1460
# NOP
TCP Option - No-Operation (NOP)
Kind: No-Operation (1)
# 窗口擴大因子
TCP Option - Window scale: 8 (multiply by 256)
Kind: Window Scale (3)
Length: 3
Shift count: 8
三 未來計划
- 學習TCP是為了更好地理解MQTT協議(即自頂向下的學習方式,以前自底向上學過一段時間,效果一般,因為沒有應用場景)
- TCP學完之后,將補充HTTP協議(基於TCP協議)
- HTTP協議之后,將學習WebSocket協議,並最終回到MQTT協議(能夠基於WebSocket協議進行傳輸)