序列号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