这里序号是两个部分之和。第一部分是一个随机初始值,这个随机初始值由发起方生成。第二部分是TCP报文体中封装的数据段,在原始数据报文中的字节偏移位置值。

之后是确认号:
确认号有两个作用
1、确认号就是告诉TCP通信的另一方,自己已经收到了对方发的TCP报文。
2、告诉另一方下次该请求哪个数据包
在TCP建立连接阶段:
发起方第一次握手时,发送的TCP报文的头部会携带一个序号(随机值),接收方收到第一次握手报文后,会反馈第二次握手报文给发起方,该报文头中有一个确认号,它的计算规则是:“确认号 = 第一次握手时序号 + 1”
例如:
发起方收到第二次握手报文后,检查确认号是否比第一次握手时序号大1,是的话,则认为就是接收方确认接收到了。
并且确认号也表示希望发起方下次从 确认号指定的位置开始发起请求。
在TCP通信阶段:
比如浏览器会请求服务器的某个资源文件而发起HTTP请求,服务器会对HTTP请求回应,回应报文中包含了资源文件的大小,此时服务器会通过TCP连接来传输资源文件。注意资源文件首先会被分解为多个数据段,服务器将数据段封装为TCP报文,然后依次发送给浏览器。
此时服务器发送的TCP报文中,报文头会带一个确认号,该确认号此时的工作不再单纯是告诉浏览器自己确认收到了你的TCP请求,即确认号不再是 seq + 1了,而是告诉浏览器下次该请求哪个数据段对应的TCP数据包了。它的计算规则是: 确认号 = seq + 请求资源文件大小 - 54
为什么要减去54呢?
因为这里通过HTTP获取到请求资源文件的大小不仅包含了 原始数据段,还有各层对原始数据段的封装头信息,比如:
14字节Ethernet报头(数据链路层),20字节的IP报头(网络层),20字节的TCP报头(传输层),它们加起来就是54字节
减去这54字节,才能得到原始数据段大小。
例如:
这里ack确认号 396的计算过程就是 = 1 + 449 - 54
再比如
这里服务器让客户端下次从854位置开始请求,这个确认号计算过程是:396 + 512 - 54 = 854
目前TCP报文头中的序号和确认号已经能够帮助通信双方来识别对方是否已经确认收到消息了,但是这样就能实现可靠传输了吗?
还不行。
TCP还有一种应对 无确认反馈的机制。即发起方发起TCP报文请求后,接收方如果不及时反馈确认收到消息给发起方,则发起方会认为接收方没有收到,会再次重发。同样地,如果接收方发起TCP报文给发起方,如果发起方没有及时给出确认收到消息反馈,则接收方也会重发。