TCP中的Seq和Ack理解--以一次完整连接为例
Liu Feng Lv1

关于Seq和Ack的理解

一次TCP连接中的所有有效数据都会被标号, SYN报文和FIN报文也占用一个Seq号。一个TCP报文中有效数据的第一个字节的编号就是Seq号;一端使用Ack=x,表示该端已经收到来自对方所有字节号<x的数据,所以有种说法是“Ack号是发送方期待下一次接收到的有效数据的第一个字节编号,也即Seq号”

Seq号永远有效,Ack只有在ACK位置1时才有效。当且仅当在一次TCP连接中的第一个报文中,TCP头部才会出现ACK未被置1的情况。在剩余所有情况,ACK位均被置1。

实例分析

#1

TCP连接开始时,双方均有相对Seq=0,代表有效数据从编号0开始。第一个包中ACK位未被置1,所以对于客户端来说Ack编号无效(也可以认为就是0,因为没有接收到来自服务器的数据)。

#2

服务器收到客户端的SYN报文,自己也发送一个SYN报文,Seq=0代表服务器端的有效数据编号从0开始,Ack=1表示自己已经收到来自客户端的编号<1的数据,也就是说期望客户端下此的有效数据编号(即Seq号)从1开始。

#3

客户端收到SYN报文,发出ACK报文做回应。该报文Seq=1暗示有效数据编号从1开始,Ack=1暗示自己已经收到来自服务器的编号<1的数据。

#4

客户端做出http请求,注意该请求有效数据长度len=125,该报文Seq=1暗示有效数据编号从1开始,Ack不变是因为还没有接收到服务器发送的数据。

注:为什么#3中先服务器发送了ACK报文,但是#4中Seq却不+1?是因为单独的ACK报文不含有效数据,而SYN和FIN报文却算作有效数据。

#5

服务器回应ACK代表收到http请求,Seq=1是因为目前仍未发送额外的有效数据,Ack=1(第二步)+125(第四步len长度)=126代表服务器确认自己收到了来自客户端的编号<126的数据。

#6

服务器回应http请求,有效数据从Seq=1开始,长度len=226,Ack不变是因为从客户端接收到的有效数据没有增加。

#7 第一次挥手

服务端请求关闭连接,Seq=1(第六步)+226(第六步len长度)=227,Ack不变。

#8 第二次挥手

客户端回应ACK报文代表收到,Seq=1(第四步)+125(第四步)=126,Ack=1(第四步)+226(第六步有效数据长度)+1(第七步FIN报文)=228

注:也可以说228=227(第七步)+1(第七步FIN报文),但从第四步累加到第八步更有助于理解细节,两种做法完全等效。

#9 第三次挥手

客户端也发出FIN报文请求关闭连接,Seq仍不变(因为上一步的Ack不算有效数据),Ack也不变。

#10 第四次挥手

服务器收到FIN报文,做出ACK回应,Seq=Seq(第七步)+1(第七步FIN报文长度)=228,Ack=Ack(第七步)+1(第九步FIN报文长度)=127。至此双方均断开TCP连接。

 Comments