序列號seq,其實TCP發送payload數據的每個字節都是有編號的,每一個報文的編號其實就是這個報文payload數據中的首個字節的編號,通俗的例子:
一共發了3個報文:P1(payload=aaa), P2(payload=bb), P3(payload=c),那麼shell
P1.seq=0 P2.seq=3(P1.seq+p1.payload.length) P3.seq=5(P2.seq+p2.payload.length)
確認號ack,實際上是對前一個對端發送來的報文的回覆,ack=x+1說明以前對端發送來的x個字節的payload數據都已經收到了,請對端下次發送seq=x+1的報文吧,或者說叫指望從對端收到的下一字節的序號。通俗的例子:
A主機發來了P1(payload=aaa), B主機接收到P1報文後須要發回確認報文R1:tcp
P1.seq=0 R1.ack=3(P1.seq+p1.payload.length)
抓在80端口上的TCP包:spa
> tcpdump -S 'tcp and port 80' 21:33:01.704998 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [S], seq 396038856, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 744881175 ecr 0,sackOK,eol], length 0
其中傳輸的Flags釋義:3d
> tcpdump -S 'tcp and port 80' 21:33:01.704998 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [S], seq 396038856, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 744881175 ecr 0,sackOK,eol], length 0 21:33:01.717502 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [S.], seq 2345237966, ack 396038857, win 14400, options [mss 1412,nop,nop,sackOK,nop,wscale 7], length 0 21:33:01.717542 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345237967, win 4096, length 0 21:33:01.718011 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [P.], seq 396038857:396039622, ack 2345237967, win 4096, length 765: HTTP: POST /mmtls/22207be4 HTTP/1.1 21:33:01.727958 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [.], ack 396039622, win 125, length 0 21:33:01.758550 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [P.], seq 2345237967:2345238289, ack 396039622, win 125, length 322: HTTP: HTTP/1.1 200 OK 21:33:01.758735 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345238289, win 4090, length 0 21:33:01.759551 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [F.], seq 2345238289, ack 396039622, win 125, length 0 21:33:01.759693 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [.], ack 2345238290, win 4090, length 0 21:33:01.773281 IP 192.168.31.72.61146 > 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http: Flags [F.], seq 396039622, ack 2345238290, win 4096, length 0 21:33:01.786917 IP 101.165.151.61.dial.xw.sh.dynamic.163data.com.cn.http > 192.168.31.72.61146: Flags [.], ack 396039623, win 0, length 0
梳理一下:code
報文傳輸方向 | Flags | seq | ack | payload length |
---|---|---|---|---|
C -> S | [S] | 396038856 | 0 | |
S -> C | [S.] | 2345237966 | 396038857 | 0 |
C -> S | [.] | (396038857) | 2345237967 | 0 |
C -> S | [P.] | 396038857(:396039622) | 2345237967 | 765 |
S -> C | [.] | (2345237967) | 396039622 | 0 |
S -> C | [P.] | 2345237967(:2345238289) | 396039622 | 322 |
C -> S | [.] | (396039622) | 2345238289 | 0 |
S -> C | [F.] | 2345238289 | 396039622 | 0 |
C -> S | [.] | (396039622) | 2345238290 | 0 |
C -> S | [F.] | 396039622 | 2345238290 | 0 |
S -> C | [.] | (2345238290) | 396039623 | 0 |
下面圖示了整個鏈接、傳輸和斷開過程的TCP數據報:
blog
其中須要注意的點有:it
seq 396038857:396039622 length 765
,這個意思是seq=396038857,其報文的payload length=765,因此對端ack的時候應該ack=396039622(即表示396039622前的字節我都收到了,下一次請給我編號爲396039622及之後的字節),顯示這個就不須要人讀的時候再手工計算了,簡單明瞭的展現清楚,不過第一次用的話會很懵。報文5ack 396039622
印證了這個觀點;能夠對照此經典圖進行分析(不過要注意這個圖裏數據傳輸過程當中的數據報文假定payload length=1):
io