什麼是TCP協定?
TCP 是面向連接配接的,保證高可靠連性(資料無丢失,資料不錯位,資料不亂序,資料無重複)的傳輸協定。
TCP頭

- 源端口和目的端口 各占2個位元組,分别些人源端口号和目的端口号。
- 序号 占4個位元組,範圍是 【0 - 2^32-1 】 4284967296 個序号。序号增加到 2^32-1 ,下一個序号又回到0 ,序号使用 mod 2^32 運算。也叫做封包段序号。
- 确認号 占 4個位元組 期望收到對方下一個封包段的第一個資料位元組的序号,比如 B 正确收到了 A 發送過來的一個封包段。其封包序号字段值是501,而資料長度是 200 位元組 ,(序号501-700),這個表名B正确收到了 A 發送的到序号700為止的資料,B期望收到的下一個序号是701 ,于是 B 再發送給A 的确認封包段中确認号置為 701。
- 資料偏移 占4位,指出的是 TCP 封包段的資料起始處距離 TCP 封包段的起始處有多遠。這個字段其實上也是指出 TCP 封包段的首部長度。 機關是4位元組 ,4位能表示最大數是 15 ,首部最大長度即為 15*4位元組 = 60 位元組。
- 緊急 URG 當 URG = 1 時,表示緊急指針字段有效,表示封包段中有緊急資料, 應盡快發送,而不是按照原來的排隊順序發送。場景是,已經發送了一個很長的一個程式,需要遠端主機上 運作,由于一些原因,要取消該程式運作,是以使用者發送中斷指令 Control+C,如果不使用緊急資料,那麼這兩個字元将存儲在TCP的緩存末尾。隻有在所有資料發送完畢之後,這兩個字元才能傳遞到接收方程式上,浪費了很多時間。
- 确認ACK 僅當 ACK =1 是确認号字段才有效,當 ACK =0 是,确認好無效。TCP 規定,在連接配接建立後所有傳輸的封包都必須把 ACK 置1
- 推送PSH 當兩個應用程序進行互動式通訊是,有時在一端的應用程序希望鍵入一個指令後立即就能收到對方的響應。在這種情況。TCP 就可以使用推送 push 操作。
- 複位 RST 當 RST = 1時,表明 TCP 連接配接中出現嚴重的差錯(如 由于主機崩潰或其他原因),必須釋放連接配接,然後再重建立立運輸連接配接。
- 同步 SYN 在連接配接建立時用來同步序号,當SYN =1 而ACK =0 時,表明這是一個連接配接請求封包段。對方如果同意建立連接配接,則應在影響的封包段使用 SYN = 1 和Ack =1 ,是以,SYN 置成 1 表示這是一個連接配接請求或者連接配接接受封包。
- 終止 FIN 用來釋放一個連接配接,當 FIN = 1 時,表名此封包段的發送方的資料已經發送完畢,并要求釋放運輸連接配接。
- 視窗 占 2個位元組, 視窗是 【0,2^16 -1】之間的整數,視窗指的是發送本封包段的乙方的接收視窗, 視窗值告訴對方:從本封包段首部中的确認号算起,接收方目前允許對方發送的資料量。 為啥要有這個限制,因為接收方的資料緩存空間是有限的。
- 校驗和 占 2 個位元組。校驗和字段校驗的範圍包括首部和資料這兩部分。
- 緊急指針 占 2個位元組 緊急指針金在 URG =1 時才有意義,它指出本封包段的緊急資料的位元組數 ,是以緊急指針指出了緊急資料的末尾在封包段中的位置,所有緊急資料都處理完時, TCP 就告訴應用程式恢複到正常操作值。
- 選項 長度可變, 最長可達到 40 位元組,當沒有使用選項時, TCP 首部的長度是 20 位元組。
校驗和計算
發送時:
1、把校驗和字段設定為0;
2、把需要校驗的資料看成以16位為機關的數字組成,依次進行二進制反碼求和;
3、把得到的結果存入校驗和字段中
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum2(msg):
s = 0
for i in range(0, len(msg), 2):
w = (ord(msg[i]) << 8) + ord(msg[i + 1])
s = carry_around_add(s, w)
return ~s & 0xffff
複制
接收時
1、把首部看成以16位為機關的數字組成,依次進行二進制反碼求和,包括校驗和字段;
2、檢查計算出的校驗和的結果是否為0;
3、如果等于0,說明被整除,校驗和正确。否則,校驗和就是錯誤的,協定棧要抛棄這個資料包。
def checksum(data): # calculate checksum
s = 0
n = len(data) % 2
for i in range(0, len(data) - n, 2):
s += ord(data[i]) + (ord(data[i + 1]) << 8)
if n:
s += ord(data[i + 1])
while (s >> 16):
s = (s & 0xFFFF) + (s >> 16)
s = ~s & 0xffff
return s
複制
TCP 可靠傳輸
接收序号和确認序号,在途中有資料丢失的情況下,傳回ACK序号進行重發。
TCP的特點
- 面向連接配接的傳輸層協定
- 每一條TCP連接配接隻能有兩個端點
- 提供可靠傳遞的服務
- 提供全雙工通信
- 面向位元組流
建立連接配接: TCP 三次握手
1. A 向 B 發出連接配接請求封包段,此時首部 SYN = 1 同時選擇一初始序号 seq = x
2. B 接收連接配接請求封包段後,如果同意連接配接,則向 A 确認,确認封包段中 SYN 位 和 ACK 位都是 1 ,确認号 ack = x+1,同時也為自己初始一個序号 seq = y
3. A 收到 B的确認後, 還需要給 B 确認,确認封包段的 ACK =1 , 确認号 ack = y+1, 而自己的序号 seq = x+1
通過抓包可以看到三次握手建立連接配接如下:
斷開連接配接:四次揮手
- A 向 B 發送連接配接釋放封包端,并停止發送資料,主動關閉 TCP 連接配接,封包端首部 FIN 設定成1 ,序号 seq = u ,它等于前面已經傳輸過來的最後一個自己的序号+1
- B 接收連接配接釋放封包後發送确認封包 ,确認号 ack = u+1, 而這個封包段自己的序号是v, 等于B前面已經傳送狀态的最後一個位元組序号+1
- A 收到 B的确認信号之後,進入終止等待狀态,等待B發送的連接配接釋放封包B 發送連接配接釋放封包,必須重複上次發送的确認号 ack = u+1 ,B 進入最後确認狀态 等待 A 确認
- A 收到B的連接配接釋放封包後,發送确認 ACK = 1, 确認好 ack = w+1 ,序号 seq = u+1
通過抓包可以看到,斷開連接配接如下: