我是靠谱客的博主 称心夕阳,最近开发中收集的这篇文章主要介绍计算机网络-传输层篇-TCP协议的可靠传输,流量控制,拥塞控制与传输效率,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  • 目录

    TCP的可靠传输

    TCP协议的流量控制与传输效率

    概述

    滑动窗口回顾

    发送窗口与接收窗口

    TCP的流量控制

    捎带确认

    TCP的传输效率

    TCP的拥塞控制

    概述及由来

    过程简单谈

    拥塞控制的四个算法


  • TCP的可靠传输

  • TCP的可靠传输基于连续ARQ协议
  • TCP的滑动窗口以字节为单位
  • 窗口的大小表示窗口里面的字节都是可以发送的
  • 假如说窗口大小为7
  • 窗口里七个字节都已经发送出去,但是没有收到确认,那么可用窗口就为0
  • 考虑下面一种情况:
  • 当收到5和7字节的确认消息时,因为当前确认消息并不是按顺序的,3和4的确认消息还没有过来;
  • 如果过了超时时间之后还未收到3和4的确认消息,那么就会从3重新传输这七个字节
  • 由此可见,可靠传输效率并不高
  • 因为前面已经收到5和7的确认号,但因为3和4并没有收到,所以还需要重传
  • 解决这一问题可以通过选择重传的方法
  • 选择重传
  • 选择重传需要指定需要重传的字节
  • 这里的字节是指需要重传的字节边界
  • 例如1000~1500这一段里的500个字节丢失,需要重传,那么就会把1000和1500这两个数字存入TCP的选项里;
  • 因为TCP的报文一次传输是传输多个字节,而不是一个字节,在丢失的情况下,其实丢失的是整个TCP报文
  • 对于整个TCP报文都丢失的情况下,在报文里的一整段字节流都是丢失的;
  • 选择重传机制里需要重传的字节边界存放在TCP头部的TCP选项里
  • TCP协议的流量控制与传输效率

  • 概述

  • 一般来说,我们总希望数据传输的更快一些
  • 但如果发送方把数据发得过快,接收方就可能来不及接收,这就会造成数据的丢失
  • 所谓流量控制(flow control)就是根据接收方的实际接收能力,来控制发送方的数据发送速率
  • 从而让发送方的发送速率不要太快,要让接收方来得及接收
  • 流量控制解决的是一个端到端的问题
  • 是接收端控制发送端发送数据的速率,以便使接收端来得及接收
  • TCP协议使用滑动窗口机制来实现对发送方的流量控制
  • 利用滑动窗口机制可以很方便地在TCP连接上实现发送方流量控制
  • 通过接收方的确认报文中的窗口字段,发送方能够准确地控制发送字节数
  • 滑动窗口回顾

  • 发送方发送数据时不再是一次只发送一个TCP报文段,而是一次连续发送多个报文段
  • 也就是说,发送方在发送了一个段之后不必一直等待这个段的确认应答,而是继续发送下一个报文段
  • 每当收到一个报文段的确认应答后,窗口就向前滑动一个报文段的长度
  • 因为已发送并收到确认应答的报文段不需要再保留在窗口中了
  • 但已发送还未收到确认应答的段还必须保留在窗口中,以便在超时重传时使用
  • 需要注意的是,滑动窗口是以字节为单位向前滑动的
  • 窗口以外的部分中
  • 窗口左边部分表示已发送且已收到确认应答
  • 这些数据显然不需要再保留了
  • 窗口右边部分表示不允许发送的数据
  • 因为接收方都没有为这部分数据保留临时存放的缓存空间
  • 可以发现,发送窗口的位置由窗口左边界和右边界共同确定
  • 发送窗口左边界每次都是滑动到收到确认应答号的位置上
  • 而发送窗口右边界则是不允许发送数据的第1个字节序号
  • 这种可以顺序地将多个报文段同时发送以提高TCP通信性能的机制,被称为滑动窗口机制
  • 发送窗口与接收窗口

  • 上面所讲的内容是从发送方的角度来解释滑动窗口机制的
  • 发送方的窗口称为发送窗口
  • 而接收方也有一个窗口,称为接收窗口
  • 发送窗口,表示的是发送方一次可以连续发送出去的数据量,以字节为单位
  • 凡是已经发送过的数据,在未收到确认之前都必须暂时保留在发送窗口中,以便在超时重传时使用
  • 发送窗口内的数据都是尚未收到确认应答的
  • 接收窗口,表示的是接收方一次能够连续接收的数据量,以字节为单位
  • 接收窗口内的数据都是允许被接收的
  • 在TCP报文段的首部结构中
  • 有一个“窗口”字段,其作用是告诉对方本端的接收窗口的大小,以便控制发送方的发送窗口大小
  • 二者的关系:发送窗口值 ≤ 接收窗口值
  • 此外,发送方的发送窗口大小还要受到当前网络拥塞程度的制约
  • 发送窗口右边界的变化有两种情况:
  • 一是不动(没有收到新的确认应答);
  • 二是前移(收到了新的确认应答)
  • 发送窗口通常是不断向前移动的
  • 要描述一个发送窗口的状态需要三个指针:P1,P2 和 P3
  • 指针都指向字节的序号
  • 这三个指针指向的几个部分的意义如下:
  • P3 - P1 = A(发送方)的发送窗口
  • P2 - P1 = 已发送但尚未收到确认的字节数
  • P3 - P2 = 允许发送但目前尚未发送的字节数(又称为可用窗口或有效窗口)
  • TCP的流量控制

  • 上面的部分讲了滑动窗口机制
  • 知道了滑动窗口机制可以提高TCP通信的传输速率,同时利用滑动窗口机制还可以很方便地实现对TCP的流量控制
  • 所谓TCP的流量控制,它控制的对象是谁?解决的是什么问题?
  • TCP控制的对象是发送方
  • 解决的问题是控制发送方的数据发送速率问题
  • 接下来就要弄清楚,TCP是如何利用滑动窗口机制来解决这个流量控制问题的?
  • 下面通过一个例子来说明如何利用滑动窗口机制进行流量控制
  • 假设,数据传输方向是 A —> B
  • 在三次握手建立连接时,B 告诉了 A:“我的接收窗口是 rwnd=400”(这里rwnd 表示 receiver window)
  • 因此,发送方的发送窗口不能超过接收方给出的接收窗口的数值
  • 请注意,TCP 的窗口大小的单位是字节,而不是TCP报文段
  • 例接收方的主机 B 进行了三次流量控制
  • 第一次把接收窗口减小到 rwnd = 300,第二次又减小到 rwnd = 100,最后减小到rwnd = 0,即不允许再发送数据了
  • 这种使发送方暂停发送的状态将一直持续到接收方主机 B 重新发出一个新的窗口值为止
  • 还应注意到,接收方 B 向 发送方 A 发送的三个报文段都设置了 ACK=1,这是因为只有在 ACK=1 时确认号字段才有意义
  • 现在考虑一种情况
  • B 向 A 发送了零窗口的报文段后不久,B 的接收缓存又有了一些存储空间
  • 于是 B 向 A 发送了 rwnd=400 的报文段
  • 然而这个报文段在传送过程中丢失了
  • A 一直等待收到 B 发送的非零窗口的通知,而 B 也一直在等待 A 发送的数据
  • 如果没有其他措施,这种互相等待的死锁僵局将一直延续下去
  • 为了解决这个问题,TCP 为每一个连接设有一个持续计时器(persistence timer)
  • 只要TCP连接的一方接收到对方的零窗口通知,就启动持续计时器
  • 若持续计时器设置的超时时间到期,就发送一个零窗口探测报文段(仅携带一个字节的数据)
  • 而对方就可在确认这个探测报文段时给出现在新的窗口值
  • 如果窗口值仍为零,那么收到这个报文段的一方就重新设置持续计时器
  • 如果窗口值不为零,那么死锁的僵局就可以打破了
  • 说明:TCP规定,即使设置为零窗口,也必须接收以下几种报文段:
  • 零窗口探测报文段、确认报文段(ACK=1)和携带紧急数据的报文段(URG=1)
  • 捎带确认

  • 在计算机通信中,当一个数据帧到达的时候
  • 接收方并不是立即发送一个单独的 控制帧,而是抑制一下自己并且开始等待,直到网络层传递给它下一个分组
  • 然后,确认信息被附在往外发送的数据帧上(使用帧头中的ask域)
  • 实际上,确认报文搭了下一个外发数据帧的便车
  • 这种“将确认暂时延迟以便可以钩到下一个外发数据帧”的技术称为捎带确认(piggybacking)
  • 当主机收到远程主机的TCP数据包之后,通常不马上发送ACK数据包,而是等上一个短暂的时间
  • 如果这段时间里面主机还有发送到远程主机的TCP数据包,那么就把这个ACK数据包“捎带”着发送出去,把本来两个TCP数据包整合成一个发送
  • 一个TCP连接允许数据在任何一个方向流动,并允许任何一个应用程序在任何时刻发送数据
  • 即当两个进程 A 和 B 建立连接后,任何一方均能发送数据给另一方
  • 当分组从 A 发往B 时,可携带对 B 发来数据的确认
  • 同理,当分组从 B 发往 A 时,可携带对 A 发来数据的确认
  • 即采用捎带确认的机制
  • TCP的传输效率

  • 前面已经讲过,应用进程把数据传送到 TCP的发送缓存后
  • 剩下的发送任务就由 TCP来控制了
  • 可以用不同的机制来控制 TCP 报文段的发送时机
  • 例如,第一种机制是 TCP 维持一个变量,它等于最大报文段长度MSS
  • 只要缓存中存放的数据达到MSS字节时,就组装成一个 TCP 报文段发送出去
  • 第二种机制是由发送方的应用进程指明要求发送报文段
  • 即 TCP 支持的 推送(push)操作
  • 第三种机制是发送方的一个计时器期限到了
  • 这时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去
  • 但是,如何控制 TCP 发送报文段的时机仍然是一个较为复杂的问题
  • 例如,一个交互式的用户使用Telnet连接(传输层为TCP协议)
  • 假设用户只发一个字符,加上20字节的TCP首部后,得到21字节长的 TCP 报文段
  • 再加上 20 字节的 IP 首部,形成 41 字节长的 IP 数据报
  • 在接收方 TCP 收到数据后立即发出确认,构成的 IP 数据报是40字节长(假定没有发送数据)
  • 若用户要求远地主机回送这一字符,则又要发回 41 字节长的 IP 数据报和 40 字节长的确认IP数据报
  • 这样,用户仅发1个字符的数据,线路上就需传送总长度为 162 字节共 4 个报文段
  • 当线路带宽并不富裕时,这种传送方法的效率的确不高
  • 因此应适当推迟发回确认报文,并尽量使用捎带确认的方法
  • 在TCP的实现中广泛使用Nagle(纳格)算法;算法如下:
  • 1、若发送应用进程把要发送的数据逐个字节地送到 TCP 的发送缓存
  • 则发送方就把第一个数据字节发送出去,把后面到达的数据字节都先缓存起来
  • 2、当发送方接收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段再发送出去,同时继续对随后到达的数据进行缓存
  • 只有在收到对前一个报文段的确认后,才继续发送下一个报文段
  • 3、当数据到达较快而网络速率较慢时,用这样的方法可明显地减少所用的网络带宽
  • 4、Nagle算法还规定:当到达的数据已达到发送窗口大小的一半或已经达到报文段的最大长度时,就立即发送一个报文段
  • 另一个问题叫糊涂窗口综合症(silly window syndrome)[RFC 813]
  • 有时也会使 TCP 的性能变坏
  • 设想一种情况:
  • TCP 接收方的缓存已满,而交互式的应用进程一次只从接收缓存中读取 1 个字节(这样就使接收缓存空间仅腾出 1 个字节),然后向发送方发送确认,并把窗口设置为 1 个字节(但发送的数据报为 40 字节长)
  • 接着,发送方又发来 1 个字节的数据(请注意,发送方的 IP 数据报是 41 字节长)
  • 接收方发回确认,仍然将窗口设置为 1 个字节
  • 这样进行下去,使网络的传输效率很低
  • 要解决这个问题
  • 可以让接收方等待一段时间,使得或者接收缓存已有足够空间容纳一个最长的报文段MSS
  • 或者等到接收方缓存已有一半空闲的空间
  • 只要出现这两种情况之一,接收方就发出确认报文,并向发送方通知当前的窗口大小
  • 此外,发送方也不要发送太小的报文段,而是把数据积累成足够大的报文段,或达到接收方缓存的空间的一半大小
  • 上述两种方法可以配合使用
  • 使得在发送方不发送很小的报文段的同时,接收方也不要在缓存刚刚有了一点小的空间就急忙把这个很小的接收窗口大小信息通知给发送方
  • TCP的拥塞控制

  • 概述及由来

  • 前面的流量控制是避免发送方的数据填满接收方的缓存,但并不知道网络中发生了什么
  • 流量控制考虑点对点的通信量的控制
  • 拥塞控制考虑整个网络,是全局性的考虑
  • 一般来说,计算机网络都处在一个共享的环境
  • 因此也有可能会因为其他主机之间的通信使得网络拥堵
  • 在网络出现拥堵时,如果继续发送大量的数据包,可能会导致数据包时延、丢失,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大…
  • 过程简单谈

  • 于是,就有了拥塞控制,控制的目的就是避免“发送方”的数据填满整个网络
  • 为了在“发送方”调节所要发送数据的数据量
  • 定义了⼀个叫做“拥塞窗口”的概念
  • 拥塞窗口cwnd是发送方维护的⼀个的状态变量,它会根据网络的拥塞程度动态变化的
  • 在前面提到过发送窗口 swnd 和接收窗口 rwnd 是约等于的关系
  • 那么由于加入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd)
  • 也就是拥塞窗口和接收窗口中的最小值
  • 拥塞窗口 cwnd 变化的规则:
  • 只要网络中没有出现拥塞,cwnd 就会增⼤;
  • 但网络中出现了拥塞,cwnd 就减少;
  • 只要“发送方”没有在规定时间内接收到 ACK 应答报文,也就是发⽣了超时重传,就会认为网络出现了拥塞
  • 拥塞控制的四个算法

  • 慢启动(slow-start)、拥塞避免(congestion avoidance)、快重传(fast retransmit)、快恢复(fast recovery)
  • 慢启动
  • TCP在刚建立连接完成后
  • 首先是有个慢启动的过程,这个慢启动的意思就是⼀点⼀点的提高发送数据包的数量
  • 慢启动的算法规则:
  • 当发送方每收到⼀个 ACK,拥塞窗口 cwnd 的大小就会加 1
  • 连接建立完成后
  • ⼀开始初始化 cwnd = 1 ,表示可以传⼀个 MSS 大小的数据
  • 当收到⼀个 ACK 确认应答后,cwnd 增加 1,于是⼀次能够发送 2 个
  • 当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这⼀次能够发送 4 个
  • 当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4个,所以这⼀次能够发送 8 个
  • 可以看出慢启动算法,发包的个数是指数性的增长
  • 有⼀个叫慢启动门限 ssthresh (slow start threshold)状态变量
  • 当 cwnd < ssthresh 时,使⽤慢启动算法
  • 当 cwnd >= ssthresh 时,就会使⽤拥塞避免算法
  • 拥塞避免
  • 前面说道,当拥塞窗口 cwnd 超过慢启动门限 ssthresh 就会进入拥塞避免算法
  • ⼀般来说 ssthresh 的大小是 65535 字节
  • 那么进入拥塞避免算法后,它的规则是:
  • 每当收到⼀个 ACK 时,cwnd 增加 1/cwnd
  • 接上前面的慢启动的例子,现假定 ssthresh 为 8 :
  • 当 8 个 ACK 应答确认到来时
  • 每个确认增加 1/8,8 个 ACK 确认 cwnd ⼀共增加 1,于是这⼀次能够发送 9个 MSS 大小的数据,变成了线性增长
  • 拥塞避免算法就是将原本慢启动算法的指数增长变成了线性增长,还是增长阶段,但是增长速度缓慢了⼀些
  • 快重传
  • 当网络出现拥塞,也就是会发生数据包重传
  • 重传机制主要有两种:超时重传、快速重传
  • 超时重传之前的总结中有介绍过,此处只说一下快速重传
  • 快速重传算法
  • 当接收方发现丢了⼀个中间包的时候,发送三次前⼀个包的ACK,于是发送端就会快速地重传,不必等待超时再重传
  • TCP 认为这种情况不严谨,因为大部分没丢,只丢了一小部分,则 ssthresh 和 cwnd 变化如下:
  • cwnd = cwnd/2 ,也就是设置为原来的⼀半;
  • ssthresh = cwnd ;
  • 快恢复
  • 快速重传和快速恢复算法⼀般同时使用
  • 快速恢复算法是认为,你还能收到 3 个恢复 ACK 说明网络也不那么糟糕
  • 所以没有必要像 RTO 超时那么强烈
  • 进入快速恢复之前, cwnd 和 ssthresh 已被更新了:
  • cwnd = cwnd/2 ,也就是设置为原来的⼀半;
  • ssthresh = cwnd ;
  • 快速恢复算法如下:
  • 拥塞窗口 cwnd = ssthresh + 3 ( 3 的意思是确认有 3 个数据包被收到了);
  • 重传丢失的数据包;
  • 如果再收到重复的 ACK,那么 cwnd 增加 1;
  • 如果收到新数据的 ACK 后,把 cwnd 设置为第⼀步中的 ssthresh 的值
  • 原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;

最后

以上就是称心夕阳为你收集整理的计算机网络-传输层篇-TCP协议的可靠传输,流量控制,拥塞控制与传输效率的全部内容,希望文章能够帮你解决计算机网络-传输层篇-TCP协议的可靠传输,流量控制,拥塞控制与传输效率所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(51)

评论列表共有 0 条评论

立即
投稿
返回
顶部