TCP 中的Sequence Number

介绍

我们关注的就是序号确认号

这二者也是 TCP 实现可靠传输的方式。下图是一次随便抓包的截图(相对序列号)

意义

在TCP传输中,每一个字节都是有序号的,从0开始。通过序号的方式保存数据的顺序,接收端接受到之后进行重新排列成为需要的数据。

因此,我对于SEQ和ACK的了解就是:

SEQ 代表:发送的这个包中第一个字节(如果有payload的话)的序号

ACK 代表:已成功接受序列号到 ack-1 的数据,期望接收的下一个字节的序号为 ack

举例说明:

我已经发送了前100字节的数据,那么我下一个发送的包(如果发送窗口还有空间)的SEQ就是101,比如要发送10字节的数据,那么下一个包中的数据的字节编号就是 101 - 110. 之后如果继续发送的话,序号就是从111开始。

如果接收端接到了这个10字节的包的话,便会返回一个 ACK 为 111 的包,表示前面110个字节已经成功接收。

为什么SYN和FIN会消耗一个序列号

细心的同学可能会发现,为什么在建立连接的时候,发送的 SYN 包大小(payload)明明是0字节,但是接收端却返回 ACK = 1 ,还有断开连接的时候 FIN 包也被视为含有1字节的数据。

原因是 SYN 和 FIN 信号都是需要 acknowledgement 的,也就是你必须回复这个信号,如果它不占有一个字节的话,要如何判断你是回复这个信号还是回复这个信号之前的包呢?

例如:如果 FIN 信号不占用一个字节,回复 FIN 的 ack 包就可能被误认为是回复之前的数据包被重新发送了一次,第二次挥手无法完成,连接也就无法正常关闭了。

为什么SYN和ACK的初始值(ISN initialization sequence number)是一个随机值

参考TCP 的那些事儿(上)

ISN是不能hard code的,不然会出问题的——比如:如果连接建好后始终用1来做ISN,如果client发了30个segment过去,但是网络断了,于是 client重连,又用了1做ISN,但是之前连接的那些包到了,于是就被当成了新连接的包,此时,client的Sequence Number 可能是3,而Server端认为client端的这个号是30了。全乱了。RFC793中说,ISN会和一个假的时钟绑在一起,这个时钟会在每4微秒对ISN做加一操作,直到超过2^32,又从0开始。这样,一个ISN的周期大约是4.55个小时。因为,我们假设我们的TCP Segment在网络上的存活时间不会超过Maximum Segment Lifetime(缩写为MSL – Wikipedia语条),所以,只要MSL的值小于4.55小时,那么,我们就不会重用到ISN。

什么是TCP segment of a reassembled PDU

如图所示,在抓包的时候,经常会看到[TCP segment of a reassembled PDU ] 字样的包,这个代表数据在传输层被分包了。也就是代表包大小大于MTU,此处放一下MTU与MSS区别:

MTU(Maximum Transmission Unit)最大传输单元,在TCP/IP协议族中,指的是IP数据报能经过一个物理网络的最大报文长度,其中包括了IP首部(从20个字节到60个字节不等),一般以太网的MTU设为1500字节,加上以太帧首部的长度14字节,也就是一个以太帧不会超过1500+14 = 1514字节。

MSS(Maximum Segment Size,最大报文段大小,指的是TCP报文(一种IP协议的上层协议)的最大数据报长度,其中不包括TCP首部长度。MSS由TCP链接的过程中由双方协商得出,其中SYN字段中的选项部分包括了这个信息。如果MSS+TCP首部+IP首部大于MTU,那么IP报文就会存在分片,如果小于,那么就可以不需要分片正常发送。

因此,出现这种现象的原因就是你调用一次send的时候,send的数据比 MSS 还要打,因此就被协议栈进行了分包。

顺便说一下,IP数据包的分片是通过flag字段和offset字段共同完成的。

从图中可以看到,第6个和第5个包是同一个TCP报文被分成了两个包。如果我们点开看的话,可以看到两个报文的ACK序号都一样,并且这些报文的Sequence Number都不一样,并且后一个Sequence Number为前一个Sequence Number加上前一个报文大小再加上1 。这也是判断reassembled 的方式。

点开第6个包,可以看到它将5和6的数据整合起来了。

posted @ 2018-08-16 14:52  四度  阅读(15557)  评论(0编辑  收藏  举报