在重庆_那里可以做诚信网站认证,室内设计理念,lnmp wordpress,各大网站做推广的广告怎么做TCP 是一个可靠的传输协议#xff0c;解决了IP层的丢包、乱序、重复等问题。这其中#xff0c;TCP的重传机制起到重要的作用。
序列号和确认号
之前我们在讲解TCP三次握手时#xff0c;提到过TCP包头结构#xff0c;其中有序列号和确认号#xff0c; 而TCP 实现可靠传输…TCP 是一个可靠的传输协议解决了IP层的丢包、乱序、重复等问题。这其中TCP的重传机制起到重要的作用。
序列号和确认号
之前我们在讲解TCP三次握手时提到过TCP包头结构其中有序列号和确认号 而TCP 实现可靠传输的方式之一就是是通过序列号和确认应答。 序列号(Sequence Number): TCP是基于数据流的序列号用于标识数据流中的字节位置它表示数据包中的第一个字节在整个数据流中的位置。接收方在接收到数据包后会根据序列号对数据包进行排序和重组确保数据的顺序正确。 确认号(Acknowledgement Number) 确认号用于确认接收方已经成功接收了数据并且期望下一个接收到的数据包的序列号是多少。 在TCP通信中接收方会向发送方发送一个确认数据包其中包含了确认号表示接收到的数据包中的最后一个字节的下一个字节的序列号。
我们可以用wireshark抓包来看一下TCP的序列号和确认号
通过上图我们可以看到
进行三次握手时客户端的初始序列号是2924706275服务端的初始序列号是1859008164。发送第一个包时序列号是2924706276是初始序列号1表示当前数据是第一个字节数据长度8字节。服务端回复ACK时确认号是2924706284是客户端的初始序列号9表示已经接收到前8个字节现在期待第9个字节。客户端继续发第二个包序列号2924706284表示当前数据是第9个字节。服务端回复ACK时确认号是2924706292是客户端的初始序列号17表示已经接收到前16个字节现在期待第17个字节。
在wireshark中可以显示相对的序列号可以更直观地看到序列号的变化
这里我们可以看到服务端发的包序列号一直是1因为当前服务端只是接收数据并没有发送数据所以服务端的序列号一直是1而客户端的确认号也一直是1表示期待服务端发送第一个字节过来。
重传机制
正常情况下当发送端的数据到达接收主机时接收端主机会返回一个确认应答消息表示已收到消息。 但在复杂的网络下并不一定能顺利的进行数据传输万一数据在传输过程中丢失了呢针对数据包丢失的情况TCP会用重传机制解决。
超时重传
重传机制的其中一个方式就是在发送数据时设定一个定时器当超过指定的时间后如果还没有收到对方的ACK确认应答报文就会重发该数据也就是我们常说的超时重传。
那么这个指定的时间应该是多久比较合适呢 这里先介绍两个概念RTT和RTO
RTT(Round-Trip Time) 往返时延指的是数据发送时刻到接收到确认的时刻的差值也就是包的往返时间RTO(Retransmission Timeout)就是超时重传时间。
通常RTO应该略大于RTT
如果RTO太短有可能数据没有丢失就重发增加网络拥塞。如果RTO太长重发就慢性能差。
由于网络的不稳定RTT是经常变化的导致RTO也会是一个动态变化的值。
如果超时重发的数据再次超时的话下一次重传的时间间隔则会加倍。 超时重传存在的问题是超时周期可能相对较长。那是不是可以有更快的方式呢
TCP用快速重传机制来解决超时重发的时间等待。
快速重传
发送方发包的时候并不总是等待ACK的响应再发送下一个包而是会在窗口大小内连续发多个包
如果其中一个包丢失了而后续的包到达时接收方会发丢失的包的ACK给发送方。当发送方连接收到三个相同的ACK时就知道这个包丢失了于是不用等重传定时直接就可以重新发送了
通过wireshark抓包在过滤器中输入tcp.analysis.fast_retransmission我们可以观察到快速重传的现象 SACK
快速重传机制解决了超时时间的问题但是它面临着另外一个问题那就是重传的时候是重传一个包还是重传所有的包像上面的例子客户端发出19个包当触发快速重传的时候客户端只知道第2个包丢失了那其他包是否丢失客户端并不清楚这时候有两种选择
重发2~19所有的包显然会造成数据的浪费因为后面17个包都是已经收到的。只重发第2个包。但如果第3个包也丢失的话那么又得等到三次ACK才能重发第3个包效率较低。
这时候SACK(Selective Acknowledgment)选择性确认就可以起作用了。 这种方式需要在TCP头部选项字段里加一个SACK的选项它可以将已收到的数据的信息发送给发送方 这样发送方就可以知道哪些数据收到了哪些数据没收到知道了这些信息就可以只重传丢失的数据了 。
在这个例子中SACK表示15870601~15873581之间的数据是已经收到的所以客户端只需要重发15869201~15870600之间的数据就行了。 由于TCP头部大小的限制在选项中最多能支持四组SACK的数据