TCP的seq和ack号计算方法

seq和ack号存在于TCP报文段的首部中,seq是序号,ack是确认号,大小均为4字节(注意与大写的ACK不同,ACK是6个控制位之一,大小只有一位, 仅当 ACK=1 时ack字段才有效。建立 TCP 连接后,所有报文段都必须把 ACK 字段置为 1。)

seq:占 4 字节,序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0。TCP 是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号
ack:占 4 字节,期望收到对方下个报文段的第一个数据字节的序号。

1、三次握手过程中seq和ack的值:

一个TCP连接的建立是通过三次握手来实现的

1. (A) –> [SYN] –> (B)

假如服务器B和客户机A通讯. 当A要和B通信时,A首先向B发一个SYN (Synchronize) 标记的包,告诉B请求建立连接.
注意: 一个 SYN包就是仅SYN标记设为1的TCP包(参见TCP包头Resources). 认识到这点很重要,只有当B受到A发来的SYN包,才可建立连接,除此之外别无他法。因此,如果你的防火墙丢弃所有的发往外网接口的SYN包,那么你将不能主动连接外部任何主机,除非不是TCP协议。
2. (A) <– [SYN/ACK] <–(B)

接着,B收到后会发一个对SYN包的确认包(SYN/ACK)回去,表示对第一个SYN包的确认,并继续握手操作.

注意: SYN/ACK包是仅SYN 和 ACK 标记为1的包.

3. (A) –> [ACK] –> (B)

A收到SYN/ACK 包,A发一个确认包(ACK),通知B连接已建立。至此,三次握手完成,一个TCP连接完成

Note: ACK包就是仅ACK 标记设为1的TCP包. 需要注意的是当三此握手完成、连接建立以后,TCP连接的每个包都会设置ACK位
握手阶段:
序号方向seqackSYNACK
1A->B10000010
2B->A2000010000+1=1000111
3A->B1000120000+1=2000101

解释:
1:A向B发起连接请求,以一个随机数初始化A的seq,这里假设为10000,此时ACK=0

2:B收到A的连接请求后,也以一个随机数初始化B的seq,这里假设为20000,意思是:你的请求我已收到,我这方的数据流就从这个数开始。B的ACK是A的seq加1,即10000+1=10001

3:A收到B的回复后,它的seq是它的上个请求的seq加1,即10000+1=10001,意思也是:你的回复我收到了,我这方的数据流就从这个数开始。A此时的ACK是B的seq加1,即20000+1=20001

2、数据传输过程中seq和ack的值:

序号方向seqacksize
23A->B40000
70000
1514
24B->A
70000
40000+1514-54=41460
54
25A->B4146070000+54-54=700001514
26B->A70000
41460+1514-54=42920
54
解释:
23:B接收到A发来的seq=40000,ack=70000,size=1518的数据包
24:于是B向A也发一个数据包,告诉A,你的上个包我收到了。A的seq就以它收到的数据包的ack填充,ack是它收到的数据包的seq加上数据包的大小(不包括:以太网协议头=14字节,IP头=20字节,TCP头=20字节),以证实B发过来的数据全收到了。
25:A在收到B发过来的ack为41460的数据包时,一看到41460,正好是它的上个数据包的seq加上包的大小,就明白,上次发送的数据包已安全到达。于是它再发一个数据包给B。这个正在发送的数据包的seq也以它收到的数据包的ack填充,ack 就以它收到的数据包的seq(70000)加上包的size(54)填充,即ack=70000+54-54(全是头长,没数据项)。

减去54的原因见下图(链路层使用的是Ethernet II 格式,这个格式有14字节以太网首部+4字节以太网尾部):
应用数据=size-14-20-20=size-54。(假设IP首部和TCP首部都没有可选选项)
为什么不减去以太网尾部的4字节呢?
因为在物理层上网卡要先去掉前导同步码和帧开始定界符,然后对帧进行CRC检验,如果帧校验和错,就丢弃此帧。如果校验和正确,就判断帧的目 的硬件地址是否符合自己的接收条件(目的地址是自己的物理硬件地址、广播地址、可接收的多播硬件地址等),如果符合,就将帧交“设备驱动程序”做进一步处 理。这时我们的抓包软件才能抓到数据,因此,抓包软件抓到的是去掉前导同步码、帧开始分界符、FCS之外的数据


3、四次挥手过程中seq和ack的值:

TCP连接的结束是四次挥手的过程,ACK一直等于1

序号方向seqackFINACK
1A->B800009000011
2B->A9000080000+1=8000101
3B->A950008000111
4A->B8000195000+1=9500101

1. (A) –> [FIN/ACK] –> (B)
客户端A没有要发送给服务端B的数据了,想要关闭链接,则发送一个FIN=1,ACK=1的包,告诉B可以关闭连接了,我没有什么数据要给你了。
2. (A) <– [ACK] <– (B)
然后B会发送ACK=1的包给A,告诉A我知道你没有什么想给我的了,但是我还有数据要给你,你先等下,我先不想FINISH呢。
3. (A) <– [FIN/ACK] <– (B)
等B把数据都发送给A之后,B会再次发送一个包,这次FIN=1,表示我这边也想关闭了,咱俩一起关把。在2和3之间,可能还会有很多B->A的传递,ack均为80001。
4. (A) –> [ACK] –> (B)
然后A回应一个ACK,表示我知道了,一起关吧。B收到这个ACK后,就会CLOSE。但是实际上A不会直接CLOSE,还会进入一个等待时间状态TIME_WAIT,持续2倍的MSL(Maximum Segment Lifetime,报文段在网络上能存活的最大时间)。过了这个状态,才会CLOSE。为什么要等待一段时间?原因有二:
(1)保证TCP的全双工连接能够可靠关闭
假如A发送的最后一次ACK丢包了,没有被B收到,那B超时之后,会再次发送一个FIN包,然后这个包被处于TIME_WAIT状态的A收到,A会再次发送一个ACK包,并重新开始计时,一直循环这个过程,直到A在TIME_WAIT的整个过程中都没有收到B发过来的FIN包,这说明B已经收到了A的ACK包并CLOSE了,因此A这时候才可以安心CLOSE。如果A没有TIME_WAIT状态而是直接close,那么当ACK丢包之后,B会再次发送一个FIN包,但是这个包不会被A回应,因此B最终会收到RST,误以为是连接错误,不符合可靠连接的要求。因此需要等待ACK报文到达B+BRST是TCP数据报中6个控制位之一,6个控制位的作用如下:
URG 紧急:当 URG=1 时,它告诉系统此报文中有紧急数据,应优先传送(比如紧急关闭),这要与紧急指针字段配合使用。
ACK 确认:仅当 ACK=1 时确认号字段才有效。建立 TCP 连接后,所有报文段都必须把 ACK 字段置为 1。
PSH 推送:若 TCP 连接的一端希望另一端立即响应,PSH 字段便可以“催促”对方,不再等到缓存区填满才发送。
RST复位:若 TCP 连接出现严重差错,RST 置为 1,断开 TCP 连接,再重新建立连接。
SYN 同步:用于建立和释放连接,稍后会详细介绍。
FIN 终止:用于释放连接,当 FIN=1,表明发送方已经发送完毕,要求释放 TCP 连接。
(2)保证这次连接的重复数据段从网络中消失
如果A直接close了,然后向B发起了一个新的TCP连接,可能两个连接的端口号相同。一般不会有什么问题,但是如果旧的连接有一些数据堵塞了,没有达到B呢,新的握手连接就已经到B了,那么这时候,由于区分不同TCP连接是依据套接字,因此B会将这批迟到的数据认为是新的连接的数据,导致数据混乱(源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字,新旧连接的套接字很有可能相同)

总结:
确认号:
在握手和结束时确认号应该是对方序列号加1,传输数据时则是对方序列号加上对方携带应用层数据的长度,如果对方携带应用层数据长度为0,则ack与对方序列号相同,不要+1,比如25的ack与24的seq相同。也可以这样理解,因为24没有发送数据,所以A期待B下次发送过来的第一个字节的序号不变,因此25的ack与23的ack相同。
序列号:
在握手和结束时序列号应该是上次序列号+1,传输数据时则是上次的序列号加上上次应用层数据发送长度,如果数据长度为0,则seq与上次一样,不要+1,比如26的seq和24的seq相同。
TCP ACK (Acknowledgement) 和 SEQ (Sequence Number) 是 TCP 协议中用于实现可靠数据传输和流控制的重要字段。 1. ACK (Acknowledgement): ACK 字段用于确认已经成功接收到的数据。在 TCP 通信中,接收方会向发送方发送 ACK 报文,其中的 ACK 字段表示下一个期望接收的字节序。例如,如果 ACK 字段的值是 100,表示接收方已经成功接收到字节序为 99 的数据,并期望接收序为 100 的数据。 2. SEQ (Sequence Number): SEQ 字段用于标识 TCP 报文中数据的字节序。在 TCP 通信中,每个 TCP 报文都会携带一个 SEQ 字段来指示该报文中数据的起始字节序。接收方根据 SEQ 字段来按序接收和重组数据流。 通过 ACKSEQ 字段的组合使用,TCP 协议可以实现可靠的数据传输和流控制。发送方发送数据时,接收方会发送带有 ACK 字段的确认报文,以告知发送方已成功接收到数据。发送方根据接收到的 ACK 确认来确认数据是否成功传输,如果没有收到 ACK 确认,发送方会进行重传。 同时,SEQ 字段的使用也可以帮助接收方按序接收和重组分片的数据。每个 TCP 报文都会携带 SEQ 字段,接收方根据 SEQ 字段来确定数据的顺序,并将它们按序交付给应用层。 总结:TCP 中的 ACKSEQ 字段是用于实现可靠数据传输和流控制的重要字段。ACK 字段用于确认已经成功接收到的数据,SEQ 字段用于标识数据的字节序。通过这两个字段的使用,TCP 可以实现可靠的数据传输和流控制机制。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值