TCP/IP Note

《TCP/IP详解》读书笔记

一、TCP超时与重传

引言

  • 计时器超时称为重传超时(RTO)
  • 若TCP累计确认无法返回新的ACK,或者当ACK包含的选择确认信息(SACK)表明出现失序报文段时,快速重传会推断出现丢包
  • 由下层网络(IP)可能出现丢失重复或失序包,TCP重传其认为已经丢失的包

简单的超时与重传举例

  • 二进制指数退避
    • 每次重传间隔时间加倍
  • TCP拥有两个阈值来决定如何重传同一个报文段
    • R1表示TCP在向IP层传递“消极建议”(如重新评估当前路径)前,愿意尝试重传的次数
    • R2(大于R1)指示TCP应放弃当前连接的时机

设置重传超时

  • TCP超时和重传的基础根据给定连接的RTT(往返时间)设置RTO
    • 若TCP先于RTT开始重传,可能会在网络中引入不必要的重复数据
    • 若延迟远大于RTT的间隔发送重传数据,整体网络利用率(及单个连接吞吐量)会随之下降
  • RTO设置得当是保证TCP性能的关键
  • 当分组失序(或丢失)时,RTT会被过高估算。较大的RTT估计值使得RTO也更大
  • 时间戳选项(TSOPT)使得发送端即使在丢包、延时、失序的情况下也能测量RTT

基于计时器的重传

  • 对于TCP来说,计时器需要有效地实现被设置、重新设置或取消的功能
  • RTO的设置通常大于RTT(两倍或更大)
    • 因此基于计时器的重传会导致网络利用率的下降
  • 快速重传不需要计时器超时来触发且比超时重传更高效

快速重传

  • 快速重传机制基于接收端的反馈信息来引发重传
  • 快速重传是根据收到重复ACK来推断出现丢包并启动重传,而不必等待重传计时器超时
  • 快读重传仅在达到重复阈值后才被触发,而不是一旦收到重复ACK就出发,减少了大量不必要的重传发生

带选择确认(SACK)的重传

  • 空缺
    • ACK号与接收端缓存中的其他数据之间的间隔
  • 失序数据
    • 序列号高于空缺的数据
  • 在很多情况下,合理采用SACK信息能更快地实现空缺填补,且能减少不必要的重传
  • SACK接收端行为
    • SACK选项的空间有限,应尽可能确保向TCP发送端提供最新信息,其余的SACK块包含的内容也按照接收的先后依次排序
  • SACK发送端行为
    • SACK发送端记录接收到的累计ACK信息,还需要记录接收到的SACK信息
    • 当SACK发送端执行重传时,通常是由于其收到了SACK或重复SACK(D-SACK)
  • 为提高对ACK丢失的鲁棒性,第一个SACK块中需要包含之前的重复SACK信息

伪超时与重传

  • 伪重传

    • 即使没有出现数据丢失也可能引发的重传
    • 主要原因是伪超时
  • DSACK

    • 主要目的是判断何时重传是不必要的
    • 因此发送端至少可以判断是否发生了包失序、ACK丢失、包重复

包失序与重复

  • 失序
    • IP层不能保证包传输是有序进行的
    • 如果失序发生在正向链路上,TCP可能无法正确识别失序和丢包
  • 重复
    • 采用DSACK避免

重新组包

  • 定义:发送一个更大的报文段来提高性能(不能超过接收端通告的MSS,也不能大于路径MTU)
  • 当TCP超时重传,它并不需要完全重传相同的报文段
  • 解决了重传二义性问题

二、TCP数据流与窗口管理

交互式通信

  • TCP流量中通常90%或者更多的TCP报文段都包含大批量数据(如Web、文件共享、电子邮件、备份),其余部分则包含交互式数据(如远程登陆、网络游戏),批量数据通常较大,而交互式数据段则会比较小
  • 对于一个ssh连接,客户端对其传输数据加密,意味着用户输入的信息在通过连接传送前已经进行了加密
  • 每一个交互按键通常都会生成一个单独的数据包,每个按键是独立传输的(每次一个字符而非每次一行)
  • 每个输入字符会生成4个TCP数据段:客户端的交互击键输入、服务器对击键的确认、服务器端生成的回显、客户端对该回显的确认
    • 通常第二段和第三段可以合并,可将对击键的确认与回显一并传送,这种方法称为(捎带延时确认)

延时确认

  • TCP并不对每个到来的数据包都返回ACK
    • 利用TCP的累计ACK字段就能实现该功能
  • 捎带传输:
    • 累计确认可以允许TCP延迟一段时间发送ACK,以便将ACK和相同方向上需要传输的数据结合发送
  • TCP不能任意时长地延迟ACK,否则对方会误认以为数据丢失而出现不必要的重传
  • RFC指出:TCP实现ACK延迟的时延应小于500ms,实践中时延最大取200ms

Nagle算法

  • 当一个TCP连接中有在传数据(即那些已发送但还未经确认的数据),小的报文段(长度小于SMSS)就不能被发送,直到所有的在传数据都收到ACK,在收到ACK后,TCP需要收集这些小数据,将其整合到一个报文段中发送
  • ACK返回越快,数据传输越快
  • 传输包数目更少而长度更大,但同时传输时延也更长
  • Nagle算法结合ACK可能会导致某种程度的死锁(这种死锁不是永久的)
  • 要求延时尽量小的应用,建议禁用Nagle算法
    • TCP_NODELAY选项可以禁用Nagle算法

流量控制与窗口管理

  • 每一个TCP报文段(除了建立之初的包交换)都包含一个有效的序列号字段、一个ACK号或确认字段以及一个窗口大小字段(包含窗口通告信息)
  • 窗口通告:表示发送该窗口信息的通信方为即将到来的新数据预留的存储空间
  • 窗口大小:表明接收端可用缓存空间的大小
  • 滑动窗口
    • 每个TCP活动连接的两端都维护一个发送窗口结构和接收窗口结构
    • TCP以字节(而非包)为单位维护其窗口结构
    • 窗口左右边界的运动
      • 1.关闭
        • 即窗口左边界右移。当已发送数据得到ACK确认时,窗口会减小
      • 2.打开
        • 即窗口右边界右移。使得可发送数据量增大。当已确认数据得到处理,接收端可用缓存变大,窗口也随之变大
      • 3.收缩
        • 即窗口右边界左移
  • 零窗口与TCP持续计时器
    • 零窗口:左右边界相等
    • 当接收端的通告窗口值为0时,可以有效阻止发送端继续发送,直至窗口大小恢复为非零值
    • 当接收端重新获得可用空间时,会给发送端传输一个”窗口更新“告知其可以继续发送数据
      • 该窗口更新通常不包含数据(纯ACK),不能保证其传输的可靠性,容易丢包,造成死锁的发生(发送方等待收到窗口更新告知其可继续发送,接收方等待接收数据)
        • 解决方案:发送端会采用一个持续计时器间歇性地查询接收端,看其窗口是否已增长
    • TCP持续计时器会触发”窗口探测“的传输,强制要求接收端返回ACK(其中包含了窗口大小字段)
    • 窗口探测包含一个字节的数据,采用TCP可靠传输(丢失重传),因此可以避免由窗口更新丢失导致的死锁
      • 该一个字节的数据能否被接收,取决于接收端的可用缓存空间大小
    • 当TCP持续计时器超时,就会触发窗口探测的发送
    • 窗口探测的响应条件:
      • 至少为一个MSS
      • 超过总接收缓存的四分之一
    • 可以采用指数时间退避来计算持续计时器的超时
  • 糊涂窗口综合征(SWS)
    • 基于窗口的流量控制机制,尤其是不使用大小固定的报文段情况(如TCP),可能会出现SWS
    • 当出现该问题时,交换数据段不是全长的而是一些较小的数据段,由于每个报文段中有用数据相对头部信息的比例较小,因此耗费的资源也更多,相应的传输效率也更低
    • 避免SWS问题
      • 1.对于接收端来说,不应通告小的窗口值
      • 2.对于发送端来说,不应发送小的报文段
      • 为了避免SWS问题,至少满足以下条件之一时才能传输报文段(发送窗口更新)
        • (a)全长(发送MSS字节)的报文段可以发送
        • (b)数据段长度 >= 接收端通告过的最大窗口的一半的,可以发送
        • (c)满足以下任一条件的都可以发送:
          • (i)某一ACK不是目前期盼的(即没有未经确认的在传数据)
          • (ii)该连接禁用Nagle算法
    • TCP需要避免窗口收缩
    • 优先级:避免窗口收缩 > 避免SWS
  • 大容量缓存与自动调优
    • 使用较小接收缓存的TCP应用的吞吐性能更差
    • 自动调优
      • 高效地自动分配缓存大小
      • 窗口值随着接收数据的增多而增大
  • 紧急机制
    • 紧急指针字段被设置后,发送端生成的每个TCP头部都包含该字段
    • 所有序列号大于紧急指针的数据都经接收端确认

三、TCP拥塞控制

引言

  • TCP拥塞控制的难点在于怎样准确地判断何时需要减缓且如何减缓TCP传输,以及何时恢复其原有速度
  • 当网络中大量的发送方和接收方被要求承担超负荷的通信任务时,可以考虑采取(降低发送速率)或者(最终丢弃部分数据)的方法
  • 拥塞
    • 路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象

TCP拥塞检测

  • 针对丢包情况,TCP采取的首要机制是重传
    • 超时重传
    • 快速重传
  • 丢包被用作判断拥塞发生与否的值标
  • 在有线网络中,出现在路由器或交换机中的拥塞是造成丢包的主要原因
  • 在无线网络中,传输和接收错误是导致丢包的重要因素

减缓TCP发送

  • TCP头部设置的通知窗口大小字段,是TCP发送方调节发送速率的依据
  • TCP发送端发送速率 = min{接收速率,传输速率}
  • 拥塞窗口(cwnd)
    • 反映网络传输能力的变量
  • 发送端实际可用窗口W = min{cwnd,通知窗口(awnd)}
  • 在外数据值
    • 已经发出但还未经确认的数据量大小
    • 当TCP不使用选择确认机制时,W的限制作用体现为发送方发送的报文段序列号不能大于ACK号的最大值与W之和
    • 当TCP使用选择确认机制时,W用来限制在外数据值
  • 带宽延迟积(BDP)也称作最佳窗口大小
    • 若在传输数据值远高于BDP时,会引入不必要的延时

经典算法

  • TCP通过与接收端交换一个数据包来获得awnd的值
  • 获得cwnd最佳值的唯一方法是以越来越快的速率不断发送数据,直到出现数据包丢失(或网络拥塞)为止
  • 拥塞控制操作是由ACK的接收来驱动或“控制”的
  • 接收到ACK回复表明发送的数据包已被成功接收,因此可以继续发送操作
  • 自同步
    • 由一个ACK到达(称作ACK时钟)触发一个新数据包传输的关系
  • 在稳定传输状态下,整个系统可“自同步”控制

慢启动

  • 当一个新的TCP连接建立或检测到由重传超时(RTO)导致的丢包时,需执行慢启动
  • TCP发送端长时间处于空闲状态也可能调用慢启动算法
    • 在这种情况下cwnd初始值将被设置为重启窗口(RW),RW = min(IW,cwnd)
  • 慢启动的目的
    • 使TCP在用拥塞避免探寻更多可用宽带之前得到cwnd值,以帮助TCP建立ACK时钟
  • 慢启动算法防止短时间内大量数据注入导致拥塞
  • TCP以发送一定数目的数据段开始慢启动(在SYN交换之后),称为初始窗口(IW)
  • SMSS = min(接收方MSS,MTU)
  • 慢启动算法会以min(N,SMSS)来增加cwnd值,N是指在未经确认的传输数据中能通过这一”新接收的ACK号大于之前收到的ACK号“确认的字节数
  • 快速ACK模式
    • TCP操作只在慢启动阶段完成后才返回ACK

拥塞避免

  • 在慢启动阶段,cwnd会快速增长,帮助确立一个慢启动阈值,一旦达到阈值,就意味着可能有更多可用的传输资源。如果立即全部占用这些资源,将会使共享路由器队列的其他连接出现严重的丢包和重传情况,从而导致整个网络性能不稳定
  • 一旦确立慢启动阈值,TCP会进入拥塞避免阶段
  • 拥塞避免阶段窗口随时间线性增长,而慢启动阶段呈指数增长
    • cwnd1 = cwnd0+(1/k)*SMSS

慢启动和拥塞避免的选择

  • 某个TCP连接总是选择运行慢启动和拥塞避免中的一个,不会出现两者同时运行的情况
  • 当cwnd<ssthresh,使用慢启动算法
  • 当cwnd>ssthresh,使用拥塞避免
  • 当cwnd=ssthresh,任何一种算法都可以使用
  • 慢启动阈值ssthresh不是固定的,是随时间改变的
  • 慢启动阈值的主要目的是,在没有丢包发生的情况下,记住上一次”最好的“操作窗口估计值
  • ssthresh = max(在外数据值/2,2*SMSS)
  • 如果出现重传情况,慢启动阈值减小至当前窗口大小的一般(但不小于2*SMSS)

标准TCP

  • 当接收到一个好的ACK(表明新的数据传输成功)cwnd会相应更新
    • cwnd += SMSS 慢启动
    • cwnd += SMSS*SMSS/cwnd 拥塞避免
  • 当收到三次重复ACK(或其他表明需要快速重传的信号)时,会执行以下行为
    • 1.ssthresh更新为大于等式ssthresh = min(在外数据值/2,2*SMSS)的值
    • 2.启用快速重传算法,将cwnd设为(ssthresh+3*SMSS)
    • 3.每接收一个重复ACK,cwnd值暂时增加1 SMSS
    • 4.当接收到一个好的ACK,将cwnd重设为ssthresh

转发确认(FACK)和速率减半

  • 为避免出现等待空闲而又不违背将拥塞窗口减半的做法,提出了转发确认(FACK)策略
  • 带界定参数的速率减半(RHBP)
    • 基本操作:在一个RTT时间内,每接收两个重复ACK,TCP发送方可发送一个新的数据包
    • RHBP中区分了调整间隔(cwnd的修正阶段)和恢复间隔(数据重传阶段)
  • 速率减半是调节发送操作或避免集中发送的方法

限制传输

  • TCP发送方每接收两个连续的重复ACK,就能发送一个新数据包
  • TCP因此可以避免长时间等待RTO而导致吞吐性能下降
  • 速率减半也是限制传输的一种形式

    拥塞窗口校验(CWV)

  • 在发送长时间暂停的情况下,由ssthresh维护cwnd保存的”记忆”,之后cwnd值会衰减。
  • 需要区分空闲发送端和应用受限发送端
  • CWV算法原理:当需要发送新数据时,首先看距离上次发送操作是否超过一个RTO,如果超过则
    • 更新ssthresh值,设为max(ssthresh,(3/4)*cwnd)
    • 每经一个空闲RTT时间,cwnd值就减半,但不小于1 SMSS
    • 对应用受限阶段
      • 已使用的窗口大小为W_used
      • 更新ssthresh的值,设为max(ssthresh,(3/4)*cwnd)
      • cwnd设置为cwnd和W_used的平均值