计算机网络——第三章:运输层

参考书目《计算机网络:自顶向下方法(第七版)》

概述和运输层服务

  • 网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供了逻辑通信

  • 运输协议能够提供的服务不一定受制于底层网络层协议的服务模型。例如,即使网络协议不可靠或不保证机密性,运输协议也能提供可靠的数据传输或加密服务

  • IP的服务模型是尽力而为(best-effort)交付服务,它不保证报文段的交付、按序到达或完整性。从而IP被称为不可靠服务

  • 将主机间交付扩展到进程间交付被称为运输层的多路复用多路分解

  • 进程到进程的数据交付差错检查是两种最低限度的运输层服务,也是UDP所能提供的仅有的两种服务


多路复用与多路分解

  • 多路复用:从不同套接字中收集数据块并为每个数据块封装上首部信息生成报文段,之后将报文段传递到网络层
  • 多路分解:运输层报文段中的数据交付到正确的套接字
  • 主机使用IP地址端口号来将报文段导向合适的套接字(socket)

UDP的多路复用与多路分解

  • 一个UDP套接字由一个二元组全面标识,该二元组包含一个目的IP地址和一个目的端口号
  • 如果两个UDP报文段拥有不同的源IP地址或(/和)源端口号,但具有相同的目的IP地址和目的端口号,那么这两个报文段将通过相同的目的套接字被定向到相同的目的进程

TCP的多路复用与多路分解

  • 一个TCP套接字由一个四元组(源IP地址源端口号目的IP地址目的端口号)来标识的
  • 两个具有不同源IP地址或源端口号的到达TCP报文段将被定向到两个不同的套接字,除非TCP报文段携带了初识创建连接的请求(例如Web服务器的80端口)

Web服务器与TCP

  • 连接套接字与进程之间并非总是有着一对一的关系;事实上。当今高性能Web服务器通常只使用一个进程,但是为每个新的客户连接创建一个具有新连接套接字的新线程
  • 对于服务器来说,在任意给定时间都有可能有(具有不同标识的)许多连接套接字连接到相同的进程

无连接运输:UDP

  • 运输层最低限度必须提供一种复用/分解服务,以便在网络层与正确的应用级进程之间传递数据
  • 由[RFC 768]定义的UDP只是做了运输层协议能够做的最少工作
  • UDP被称为是无连接的,因为在发送报文段之前,发送方和接收方的运输层实体之间没有握手

许多使用UDP的原因

  1. 关于发送什么数据以及和何时发送的应用层控制更为精细
    • 封装报文段的速度快
    • TCP会受到拥塞控制机制的遏制,而UDP不会。因为一些实时应用通常要求最小的发送速率,不希望过分地延迟报文段的传送,且能容忍一些数据丢失
  2. 无须连接建立
    • UDP不需要任何准备即可进行数据传输。因此UDP不会引入建立连接的时延,这可能是DNS运行在UDP之上的主要原因
  3. 无连接状态
    • UDP不像TCP维护连接状态(接受和发送缓存、拥塞控制参数、序号和确认号的参数)。因而当某些应用程序运行在UDP之上而不是TCP之上时,一般都能支持更多的活跃客户
  4. 分组首部开销小
    • TCP每个报文段都有20字节的首部开销,而UDP仅有8字节
  • 注意:使用UDP的应用是可能实现可靠数据传输的。这可通过在应用程序自身中建立可靠性机制来完成(谷歌的Chrome浏览器使用的QUIC协议在UDP之上的应用层协议中实现了可靠性)

UDP报文结构

  • 长度字段指明了包括首部在内的UDP报文段长度(以字节为单位)
  • 检验和(checksum)用于差错检测功能
    • 发送方对报文段中的所有16比特字(检验和的位置被认为是全0)进行求和(求和时的溢出都被回卷),将结果的和进行反码运算并存为UDP报文段中的检验和
    • 接收方只要将全部的16比特字(包括检验和)进行相加,若结果不全为1,则表示该分组中出现了差错
    • 计算检验和的时候不足16比特字时使用0填充(zero padding)
  • 提供检验和的原因是:不能保证源和目的之间的所有链路都提供差错检测
  • 端到端原则:某些功能(例如差错检测)必须基于端到端实现,因为“与在较高级别提供这些功能的代价相比,在较低级别上设置的功能可能是冗余的或几乎没有价值的”

可靠数据传输原理

可靠数据传输为上层实体提供的服务抽象是:数据可以通过一条可靠的信道进行传输。实现这种抽象的是可靠数据传输协议(reliable data transfer, rdt)

可靠数据传输机制及其用途的总结

  • 检验和:用于检测在一个传输分组中的比特错误
  • 确认(ACK):接收方用于告诉发送方一个分组或一组分组已经被正确的接收到了
    • 确认报文通常携带着被确认的分组或多个分组的序号
    • 确认报文可以是逐个的或累积的,这取决于协议
  • 序号:用于为从发送方流向接收方的数据分组按顺序编号
    • 所接收分组的序号间的空隙可使接收方检测出丢失的分组
    • 具有相同序号的分组可使接收方检测出一个分组的冗余副本
  • 否定确认(NAK):接收方用于告诉发送方某个分组未被正确的接收。
  • 冗余ACK(duplicated ACK):用于实现与NAK一样的效果
  • 定时器:用于超时/重传一个分组,因为该分组(或其ACK)在信道中丢失了
    • 由于当一个分组延时但未丢失(过早超时),或当一个分组已被接收方收到但从接受方到发送方的ACK丢失时,可能产生超时事件,所以接受方可能会收到一个分组的多个冗余副本
  • 窗口、流水线:发送方也许被限制仅发送那些序号落在一个指定范围内的分组。
    • 通过允许一次发送多个分组但未被确认,发送方的利用率可在停等操作模式的基础上得到增加。
    • 窗口长度可根据接收方接收和缓存报文的能力、网络中的拥塞程度来进行设置

流水线可靠数据传输协议

  • 假定发送速率为\(R\)bps,所有分组长度为\(L\)比特,定义信道利用率为:发送方实际忙于将发送比特送进信道的那部分时间与发送时间之比

\[U_{sender} = \frac{\frac{L}{R}}{RTT + \frac{L}{R}}\]

  • 使用流水线可以显著增加信道利用率,其中\(W\)表示窗口大小

\[U_{sender} = \frac{W \times \frac{L}{R}}{RTT + \frac{L}{R}}\]

  • 流水线要求每个输送中的分组(不计算重传)必须有一个唯一的序号;协议的发送方和接收方也许不得不缓存多个分组
  • 解决流水线差错恢复有两种基本方法:回退N步(GBN)选择重传(SR)

流水线差错恢复:GBN(Go-Back-N)

  • 基序号(send_base):最早未确认分组的序号

  • 下一个序号(nextseqnum):最小的未使用序号(即下一个待发分组的序号)

  • N被称为窗口长度(window size),因而GBN协议也被称为滑动窗口协议

  • 四个区间:

    • 区间[0, send_base - 1]内的序号对应用于已经发送并被确认的分组
    • 区间[send_base, nextseqnum - 1]内的序号对应已被发送但未被确认的分组
    • 区间[nextseqnum, send_base + N - 1]内的序号能用于那些要被立即发送的分组
    • 大于等于send_base + N的序号是不能使用的
  • GBN发送方需响应三种类型的事件

    • 上层的调用
    • 收到一个ACK
    • 超时事件
  • GBN对序号为n的分组的确认采取累计确认

  • GBN接收方丢弃所有失序分组,并不缓存失序分组,其所需要维护的唯一信息就是下一个按序接收的分组的序号

  • 丢弃一个正确接收的分组的缺点是随后对该分组的重传也许会丢失或出错,因此甚至需要更多的重传

流水线差错恢复:SR(Selective Repeat)

  • 选择重传(SR)协议通过让发送方仅重传那些它怀疑在接收方丢失或受损的分组而避免了不必要的重传
  • SR接收方确认一个正确接收的分组而不管其是否按序
  • 注意:
    • 接收方对于收到的序号小于当前窗口基序号的分组,需要重新回复一个ACK确认(而不是忽略他们)。因为对于SR协议,发送方和接收方的窗口并不总是一致的。
    • 由于发送方和接收方的窗口不一定是一致的,从而窗口长度必须小于或等于序号空间大小的一半

面向连接的运输:TCP

  • TCP提供的是全双工(数据可以双向传输)、点对点(连接仅限于两台主机)的服务
  • MTU,即最大传输单元(Maximum Transmission Unit),表示物理接口(数据链路层)提供给其上层(通常是IP层)单次最大传输数据的大小,也表示从源到目的地的所有链路上发送的最大链路层帧
  • MSS,即最大报文段长度(Maximum Segment Size),表示TCP提交给网络层最大分段的大小,指报文段里数据的最大长度,不是指包括首部的TCP报文段的最大长度
  • MSS是TCP用来限制应用层的最大发送字节数,是TCP能发送的分组的最大长度
  • MSS是系统默认的,就是系统TCP/TP栈所能允许的最大包。在建立连接时,这个值已经确定了,这个值并不是客观的值,而是由TCP/IP的实现确定的
  • 以太网和PPP链路层协议都具有1500字节的MTU,因此MSS的典型值为1460字节(1500 - 20(IP首部)- 20(TCP首部) = 1460)

TCP报文结构

  • 序号(Seq):序号建立在传送的字节流之上,因此一个报文段的序号是该报文段首字节的字节流编号

  • TCP连接的双方均可随机地选择初始序号

  • 确认号(ACK):主机A填充进报文段的确认号是主机A期待从主机B收到的下一字节的编号

  • TCP使用累计确认

往返时间的估计与超时

  • TCP使用超时/重传机制来处理报文段的丢失
  • SampleRTT:某报文段被交给网络层到对该报文段的确认被收到之间的时间量
  • EstimatedRTT:对SampleRTT使用指数加权移动平均得到,\(\alpha\)的推荐值为0.125

\[EstimatedRTT = (1 - \alpha) \times EstimatedRTT + \alpha \times SampleRTT\]

  • DevRTT:用于估计SampleRTT偏离EstimatedRTT的程度

\[DevRTT = (1 - \beta) \times DevRTT + \beta \times |SampleRTT - EstimatedRTT|\]

  • TimeoutInterval定义为经验上的TCP超时重传间隔,推荐的初始值为1秒

\[TimeoutInterval = EstimatedRTT + 4 \times DevRTT\]

流量控制

流量控制的目的是为了消除发送方使接收方缓存溢出的可能性

TCP连接管理

  • 建立TCP连接的三次握手:
    1. 第一步:客户端的TCP首先向服务端发送SYN报文段,其中SYN比特被置为1,同时客户会随机选择一个初始序号Seq(client_isn)并封装到该报文段中
    2. 第二步:服务端回复SYNACK报文段,其中SYN比特被置为1,该报文段的ACK被置为client_isn + 1,最后服务端选择自己的初始序号Seq(server_isn)并封装到该报文段中
    3. 客户端对收到SYNACK报文段进行回复。将该报文的ACK置为server_isn + 1,同时将SYN比特置为0。第三次握手可以在报文段负载客户端到服务端的数据
  • 断开TCP连接的四次挥手:
    1. 客户端发送FIN给服务端
    2. 服务端收到FIN并回复ACK,并发送FIN,准备关闭连接
    3. 客户端收到FIN并回复ACK,并发送FIN,然后关闭连接
    4. 服务端收到ACK,关闭连接

拥塞控制原理

  • 网络拥塞的代价:
    1. 分组的到达速率接近链路容量时,分组将经历巨大的排队时延
    2. 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组
    3. 发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本
    4. 当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了
  • 拥塞控制方法:
    1. 端到端拥塞控制。端系统需对网络行为的观察(如丢失与时延)来推断网络状况。如TCP
    2. 网络辅助的拥塞控制。在网络辅助的拥塞控制中,路由器向发送方提供关于网络中拥塞状态的显式反馈信息。如显式拥塞控制ECN

TCP拥塞控制

一图胜千言。。。

\[一条连接的平均吞吐量 = \frac{1.22 \times MSS}{RTT \sqrt{L}}\]

TCP拥塞控制发展演进

  1. Tahoe 是 TCP 的早期版本,包括3 个最基本的拥塞控制算法:“慢启动” , “拥塞避免”和“快速重传”,“快速重传”根据 3 个重复的应答报文来判断报文的丢失,减少了超时重传的发生.
  2. Reno 在 Tahoe的基础上增加了“快速恢复”[25].“快速恢复”使用“管子”模型的“报文守恒”特性.发送方每收到一个重复的应答,就认为已经有一个报文离开网络,于是将发送方的拥塞窗口加一.
  3. NewReno 对 Reno中“快速恢复”算法进行了补充.它考虑了一个发送窗口内多个报文丢失的情况.在“快速恢复”算法中,发送方收到一个不重复的应答后就退出“快速恢复”状态.而在NewReno 中,只有当所有报文都被应答后才退出“快速恢复”状态.
  4. SACK 也关注一个窗口内多个报文的丢失,它使用“选择性重复”(selective repeat)策略
  5. TCP Vegas通过观察TCP连接中RTT值改变感知网络是否发生拥塞,从而控制拥塞窗口大小