网络基础(四) TCP的可靠传输

TCP协议的复杂性和功能

应用层向TCP层发送用于网间传输的、用字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把结果包传给IP层,由它来通过网络将包传送给接收端实体的TCP层。TCP为了保证不发生丢包,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的包发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据包就被假设为已丢失将会被进行重传。TCP用一个校验和函数来检验数据是否有错误;在发送和接收时都要计算校验和。
IP层并不保证数据报一定被正确地递交到接收方,也不指示数据报的发送速度有多快。正是TCP负责既要足够快地发送数据报,以便使用网络容量,但又不能引起网络拥塞:而且,TCP超时后,要重传没有递交的数据报。即使被正确递交的数据报,也可能存在错序的问题,这也是TCP的责任,它必须把接收到的数据报重新装配成正确的顺序。简而言之,TCP必须提供可靠性的良好性能,这正是大多数用户所期望的而IP又没有提供的功能。

检验和(发送方填充)

TCP将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP将丢弃这个报文段和不确认收到此报文段(则发送端超时并重发)。

序列号

将每个字节的数据进行编号。
这样做的原因:

  • 1.根据序列号确认字节数据的有效传输,即确认应答;
  • 2.既然TCP报文段作为IP数据报来传输,而IP数据报的到达可能会失序,因此TCP报文段的到达也可能会失序。如果必要,TCP将对收到的数据根据序列号进行重新排序,将收到的数据以正确的顺序交给应用层;
  • 3.既然IP数据报会发生重复(延迟之类的问题),TCP的接收端必须丢弃重复的数据(也是根据序列号来判定的)。

确认应答机制

TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端实体的包的按序接收。然后接收端实体对已成功收到的字节发回一个相应的确认(ACK);如果发送端实体在合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
且每一个ACK都带有对应的确认序列号, 意思是告诉发送者, 我已经收到了哪些数据; 下一次你从哪里开始发.
在这里插入图片描述
在这里插入图片描述

连接管理机制里的三次握手阶段序列号分析

在这里插入图片描述
具体的收发数据时序列号分析

在这里插入图片描述

超时重传机制

当TCP发出一个段后,它启动一个定时器,等待目的端确认收到这个报文段。如果不能及时(在规定的定时内)收到一个确认,将重发这个报文段。TCP有延迟确认的功能,在此功能没有打开,则是立即确认。功能打开,则由定时器触发确认时间点。
由于确认应答机制,数据可能无法到达对端或者无法被确认接收,都会有数据丢失的可能性,为了最大保证数据的可靠传输,发送方会进行数据重发。

  • 主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;
  • 主机A未收到B发来的确认应答, 也可能是因为ACK丢失了
    在这里插入图片描述

那么, 如果超时的时间如何确定?
最理想的情况下, 找到一个最小的时间, 保证 “确认应答一定能在这个时间内返回”;
但是这个时间的长短, 随着网络环境的不同, 是有差异的;
如果超时时间设的太长, 会影响整体的重传效率;
如果超时时间设的太短, 有可能会频繁发送重复的包;

TCP为了保证无论在任何环境下都能比较高性能的通信, 因此会动态计算这个最大超时时间.

RTO = 超时重传时间,动态计算出来的;

RTO = 2* RTT
RTT :报文往返时间
从发送报文开始计算,直到收到确认应答,所经历的时间被称之为报文往返时间

prev:上一次报文往返时间
cur:当前报文往返时间
预测下一次报文往返时间公式: next=cur* i + prev*(1-i)
在这里插入图片描述

滑动窗口机制

滑动窗口是传输层TCP协议进行流量控制的一种手段。对于接收方而言,通告发送方自己的可以接收的缓冲区大小,以此来控制发送方发送数据的大小,从而达到流量控制的目的。

上面我们学习了确认应答机制, 对每一个发送的数据段, 都要给一个ACK确认应答,收到ACK后再发送下一个数据段,即“一问一答”。这样做有一个比较大的缺点, 就是性能较差, 尤其是数据往返的时间较长的时候,这种“一问一答”可要把人急死。
既然这样一发一收(一问一答)的方式性能较低, 那么我们一次发送多条数据, 就可以大大的提高性能(其实是将多个数据段的等待应答时间重叠在一起了)。
在这里插入图片描述

  • 窗口大小指的是无需等待确认应答而可以继续发送数据段个数的最大值(并不是说数据段不用确认应答,只是不用一发一收,而是多条收发)。上图的窗口大小就是4000个字节(发了四个段).
  • 发送前四个段的时候, 不需要等待任何ACK, 即直接发送多个段;
  • 收到第一个ACK后, 滑动窗口向后移动, 继续发送第五个段的数据,依次类推;
    操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
  • 窗口大小可以动态变化的:是根据实时网络转发能力来决定的,每次双方进行数据收发时,都会伴随着窗口大小的协商(流量控制);
    – 网络良好,窗口就会变大,,网络的吞吐率就越高,数据发送的快;
    – 网络比较糟糕,窗口就会变小,网络的吞吐率就越低,数据发送的慢;

在这里插入图片描述
窗口移动规则: 一定要收到最早的分组的确认应答之后,才可以向后进行滑动;

那么如果窗口里出现了丢包, 如何进行重传?
这里分两种情况讨论:
情况一: 数据包已经抵达, ACK丢失了。
在这里插入图片描述
这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认;
原理:
如果消息发送方没有收到小序号的tcp报文的确认数据包,但是能收到大的确认数据包,
那就说明对端一定收到了小的序号的tcp报文,否则消息接收方不会发送大的确认数据包;
结论:
如果消息发送方接收到了更大的确认序号,但是还没有收到小的确认序号,就会忽略;不用重传;

情况二: 数据包就直接丢了
针对于消息接收方而言, 如果没有收到消息放送方发送的数据,即使接收到了更大序号的数据,也不可以进行确认回复;需要一直回复丢失的报文的起始序号(涉及到快速重传机制)。

快速重传机制

当某一段报文段丢失之后, 发送端会一直收到 1001 这样的ACK, 就像是在提醒发送端 "我想要的是 1001"一样;
如果发送端主机连续三次收到了同样一个 “1001” 这样的应答, 就会将对应的数据1001 - 2000 重新发送;
在这里插入图片描述
注意:
这个时候接收端收到了 1001 之后, 再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了, 被放到了接收端操作系统内核的接收缓冲区中;

流量控制

接收端处理数据的速度是有限的,如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应。
因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度。这个机制就叫做流量控制(Flow Control);

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端;窗口大小字段越大, 说明网络的吞吐量越高;
  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;发送端接受到这个窗口之后, 就会减慢自己的发送速度;
  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端。

假设缓冲区大小为4000,当缓冲区满了,且没被及时读走,此时窗口为0,缓冲区里无法缓存数据,在传来的数据包可能被丢弃。直到接收方读走数据,缓冲区有空闲之后,及时反馈给发送方窗口信息,然后继续发送。
在这里插入图片描述
接收端如何把窗口大小告诉发送端呢?
TCP首部中, 有一个16位窗口字段, 就是存放了窗口大小信息;
在这里插入图片描述
那么16位数字最大表示65535, 那么TCP窗口最大就是65535字节么?
实际上, TCP首部40字节选项中还包含了一个窗口扩大因子M, 实际窗口大小是 窗口字段的值与扩大因子的乘积; 即342*128=43776
在这里插入图片描述

拥塞控制机制

虽然TCP有了滑动窗口机制, 能够高效可靠的发送大量的数据,但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题。因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵,在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起丢包严重的问题。
这就需要拥塞控制机制来避免这种问题。
慢启动,拥塞避免,快重传,快恢复

慢启动与拥塞避免算法

TCP引入慢启动机制, 先发少量的数据, 探明当前的网络拥堵状态, 再决定按照多大的速度传输数据;当网络情况比较好的情况下,逐渐增大发送的数据量;
在这里插入图片描述
拥塞窗口: cwnd(congestion window)
发送开始的时候, 定义拥塞窗口大小为1;
每次收到一个ACK应答, 拥塞窗口呈现指数增长;
每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;
特点:“慢启动” 只是指初始时慢, 但是增长速度非常快(指数爆炸)。所以又引入了慢开始门限(阈值)(ssthresh),当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长(拥塞避免)。
在这里插入图片描述
特殊情况

快恢复

如果网络拥塞导致发送方某一个TCP报文丢失 ,接收方会依照快重传一连串发送3个确认包;针对于发送方而言,如果能够一连串收到三个重复的确认包, 会认为网络拥塞的并
不是很严重,完全没有从慢开始进行传输,而是设置新的慢开始门限,将拥塞窗口等于新的慢开始门限,从而直接执行拥塞避免算法;
设置新的慢开始门限=拥塞窗口/ 2

在这里插入图片描述

总结:
1.当拥塞窗口小于慢开始门门限的时候,执行慢开始算法,拥塞窗口的大小,随着传输轮次,进行指数增长
2.当拥塞窗口大于慢开始门限的时候,执行拥塞避免算法,拥塞窗口的大小,随着传输轮次,
进行线性增长
3.少量的丢包, 我们可以认为是触发超时重传(或者快重传); 大量的丢包, 我们就认为网络拥塞;当TCP通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;而拥塞控制机制, 归根结底是TCP协议想尽可能快的把数据传输给对方, 但是又要避免给网络造成太大压力的折中方案.

延迟应答机制

如果接收数据的主机立刻返回ACK应答, 这时候返回的窗口可能比较小。
假设接收端缓冲区为1M. 一次收到了500K的数据; 如果立刻应答, 返回的窗口就是500K;但实际上可能处理端处理的速度很快, 10ms之内就把500K数据从缓冲区消费掉了;在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;如果接收端稍微等一会再应答(给我点时间消化), 比如等待200ms再应答, 那么这个时候返回的窗口大小就是1M。
因为窗口越大, 网络吞吐量就越大, 传输效率就越高。 我们的目标是在保证网络不拥塞的情况下减少网络当中的数据量尽量提高传输效率;
那么所有的包都可以延迟应答么?
肯定也不是,要是都来延迟应答,虽然窗口利用大了,但是时间效率可能低了,所以又要整个折中的方法。

  • 数量限制: 每隔N个包就应答一次;
  • 时间限制: 超过最大延迟时间就应答一次;

具体的数量和超时时间, 依操作系统不同也有差异; 一般N取2, 超时时间取200ms。
隔两个包应答一次:
在这里插入图片描述

捎带应答机制

目的:也是为了减少网络当中的数据量,当接收方接收到一个数据之后,发出确认应答的时候,是随着接收方发送给发送方的数据一起,发送给发送方的;即ACK就可以搭个顺风车, 和回应的消息一起回给对端。
在这里插入图片描述

另外

面向字节流

  • 两个应用程序通过TCP连接交换字节流。TCP不在字节流中插入记录标识符。我们将这称为字节流服务。如果一方的应用程序先传10字节,又传20字节,再传50字节,连接的另一方将无法了解发方每次发送了多少字节。只要自己的接收缓存没有塞满,TCP 接收方将有多少就收多少。而一端将字节流放到TCP连接上,同样的字节流将出现在TCP连接的另一端。
  • 另外,TCP对字节流的内容不作任何解释。TCP不知道传输的数据字节流是二进制数据,还是ASCⅡ字符或者其他类型数据。对字节流的解释由TCP连接双方的应用层解释。

TCP异常情况

  • 进程终止: 进程终止会释放文件描述符, 仍然可以发送FIN(是tcp连接完成的),和正常关闭没有什么区别.
  • 机器重启: 和进程终止的情况相同.
  • 机器掉电/网线断开: 接收端认为连接还在, 一旦接收端有写入操作, 接收端发现连接已经不在了, 就会进行reset. 即使没有写入操作, TCP自己也内置了一个保活定时器, 会定期询问对方是否还在. 如果对方不在, 也会把连接释放.
    另外, 应用层的某些协议, 也有一些这样的检测机制. 例如HTTP长连接中, 也会定期检测对方的状态. 例如QQ, 在QQ断线之后, 也会定期尝试重新连接。

保活计时器

1.会定期询问对端连接,保证TCP连接是正常的;
2.产生的背景:当前这个连接已经2个小时没有发送数据了,则发送保活探测包;
3.确定要探测是否连接正常时,每隔75s发送一个保活探测包 ,连续发送10次,如果10次都没有收到确认,则认为该连接异常,需要释放该连接。

基于TCP应用层协议

HTTP
HTTPS
SSH
Telnet
FTP
SMTP

TCP小结

为什么TCP这么复杂? 那就是因为既要保证可靠性, 同时又尽可能的提高性能
可靠性:

  • 校验和(发送方填充,首部加数据部分)
  • 序列号(将每个字节的数据进行编号,按序到达)
  • 确认应答
  • 超时重传
  • 连接管理(握手挥手)
  • 流量控制
  • 拥塞控制

提高性能:

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答

其他:
定时器(超时重传定时器, 保活定时器, TIME_WAIT定时器等)

  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值