5.8.5 TCP可靠传输(一)序号确认机制
TCP是可靠的传输层协议,主要通过序号确认机制、超时重传机制、定时器三个方面实现可靠传输。
一、序号确认机制
TCP将所要传送的整个的应用层报文看成是一个一个字节组成的数据流,并对每一个传输的字节进行编号,在连接建立的时候,双方要商定一个初始的序号,TCP将每一次所传送的报文段中的第一个数据字节的序号,放在TCP首部的序号字段中。
TCP的确认是对“接收”到的数据的最高序号,也就是接收到的数据流中最后一个字节的序号表示确认,返回的确认号是期望接收的最高序号值还要加一,即确认序号表明接收方期望下次收到的第一个数据字节的序号
如图
图中所示主机A:192.168.1.100与百度服务器B:119.75.218.70之间的TCP数据通信的过程。一共有5个步骤
- 主机A向服务器B发出了247个字节的数据,这里需要注意的是由于ACK置1的报文段并不消耗序号,主机A发往服务器B的第一个数据的序号Seq=1。
- 当服务器B收到数据之后给主机A发回确认,此时的确认号是248,也就是对已收到来自于A的数据的最高序号加上1。换句话说下次主机A发送的报文段中的第一个字节的序号应该是248。而服务器B尚未向主机A发送数据,所以服务器B的序号Seq=1。
- 服务器B给主机A发送了49个字节的数据,此时服务器B的序号Seq仍然是1,因为前一个ACK标志位置1的报文段不需要消耗序号。
- 服务器B发送完成数据,期望和主机A释放连接,之前发送了49个字节的数据,所以此时服务器B的序号是50 ,这里主机A尚未对上述的3、4两个报文段进行确认
- 主机A收到数据之后对前面两个发自服务器B的报文段进行了累积确认,序号Seq=248,确认号ACK=51。因为服务器B发送了49字节的数据给主机A,并且上一个报文段的FIN=1,是需要消耗掉一个序号的。这个确认报文段同时也是对服务器B期望断开连接的确认。
由于TCP能够提供全双工通信,因此通信中的每一方都不必专门发送确认报文段。而可以在传送数据时顺便把确认信息捎带传送,这个就被成为TCP的累积确认效果,这样做可以提高传输效率。
这里我们就可以结合前面的TCP连接管理(5.8.3 TCP连接管理(一)TCP连接建立、5.8.4 TCP连接管理(二)TCP链接释放)结合在一起理解,主机A192.168.1.100访问了百度的服务器119.75.218.70和HTTP服务,主机A使用的是一般的端口号53497,服务器使用的是熟知端口号80来提供HTTP服务,我们通过三次握手机制建立起了双向的连接,主机A向服务器B发送了247个字节的数据,而服务器B向主机A发送了49个字节的数据,最后双方结束通话。连接双向释放。
二、序号确认机制思考
-
若收到的报文段没有差错,只是未按序号,那么应如何处理?
TCP未对此项做明确的规定,而是让实现者自行确定该问题。目前主要有两种确认方式
-
将不按序的报文段直接丢弃。
如图
比如发送端每个报文含有100个字节的数据,且一共连续发送了8个报文段,序号分别为1、101、201、301·····701,假设接收端正确的收到了其中的7个,而没有收到序号为201开始的100个字节的报文段,如果按照丢弃不按照顺序的报文段的方式,那么从序号201开始的所有报文段都必须重传。这种方式处理逻辑比较简单,但是效率不高,当然他也不需要缓存数据分片,因为因特网采用的数据报方式,有一些报文段没有按照顺序到达将会导致重传后续已经正确到达的所有的报文段。 -
现将其暂存于接收缓冲区内,待所缺序号的报文段收齐后再一起上交应用层。
如图
现将不按序的报文段暂存于接收的缓冲区内,待所缺序号报文段收齐之后再一起上交应用层,所以接收端可以将序号为301~701的5个报文段先换存起来,发回一个Ack确认号为201的报文段即序号为前200的字节都已经正确的收到了现在期望接收的是从201开始编号的报文段,当发送方收到这个确认之后会重发这个序号为201的报文段,当该报文段正确的到达接收端之后,接收端就立即发回一个Ack=801的确认,这样就正确的接收到了数据,当然我们看到这种方式要复杂,而且需要较大的缓存,但可以提高网络的传输效率。
-