3.1 概述和运输层服务

  • 提供了不同主机中应用进程之间的逻辑通信而非物理通信
  • 运输层协议工作在端系统
  • 发送方:将报文封装成报文段,提交给网络层
  • 接收方:解析成报文,提交给应用层
  • 提供了两种协议 TCP & UDP

运输层和网络层的关系

  • 从通信和信息处理的角度看,运输层向上面的应用层提供通信服务,属于面向通信部分的最高层,同时也是用户功能中的最底层
  • 网络层:主机之间的逻辑通信
  • 运输层:进程之间的逻辑通信

运输层的服务

  • 可靠的、有序的交付:TCP
  • 面向连接的逻辑通信:握手机制
  • 流控制:发送速度不能大于接收速度
  • 拥塞控制:从发送端系统感知、避免网络的拥塞
  • 不可靠的、无序的交付:UDP
  • 不提供必要的服务
  • 尽最大努力向网络交付数据
  • 运输层没有提供的服务
  • 最低时延保障
  • 最低带宽保障

多路复用和多路分解

  • 多路分解:将运输层报文段中的数据交付到正确的套接字

  • 多路复用:在源主机从不同的套接字中收集数据快,并为每个数据快封装上首部信息从而生成报文段,并将报文段传递到网络层

  • 端口:

  • 使用16bit的整数来标识进程

  • 在不同主机上,相同端口可能有不同的用途

  • 两种类型的端口
    01023 : 周知端口,用于标准协议,如FTP/HTTP/SMTP
    1024
    65535: 扩展端口,用于特定协议或客户端进程标识

  • 套接字:

  • UDP套接字:目的IP地址 + 一个目的端口号

  • TCP套接字:源端口号 + 源主机IP地址 + 目的端口号 + 目的主机IP地址

多路分解的机制
  • 主机收到IP数据报
  • 数据报有源IP和目的IP
  • 数据报中封装了应用报文
  • 每个报文段中标识着源端口号和目的端口号
  • 主机使用IP地址+端口号来定向应用进程的套接字
无连接的复用和分解
  • 使用端口号创建套接字: DatagramSocket mySocket1 = new DatagramSocket(99111);
  • UDP 套接字使用二元组来标识 :(dest IP address, dest port number)
  • 当主机收到UDP报文:识别报文首部的目的端口号,将报文提交给该端口号对应的应用进程
  • 不同主机发送过来的报文,只要目的端口号相同,都提交给相同的套接字
面向连接的复用和分解
  • TCP 套接字是一个四元组,包括: source IP address, source port number, dest IP address, dest port number
  • 接收端的主机通过这四个值来定位到对应的套接字
  • 服务器端的应用进程可能有并发的TCP套接字:每个套接字由一个四元组来标识
  • 如:Web服务器对为个连接的客户端创建不同的套接字:非持久性连接HTTP对每个请求创建一个套接字
  • 不同主机发送过来的报文,即使目的端口号相同,不是都提交给相同的的套接字

3.3 无连接运输:UDP

  • 不提供额外服务的运输层协议:让网络尽最大努力交付,不能解决分组失序、丢失问题
  • 是一个无连接的运输协议:UDP协议的发送端和接收端没有“握手”机制,每个分组单独处理,分组互不关联
  • 优点:
  • 时延:没有连接(握手)的过程,减少时延
  • 简单:没有连接状态管理,
  • 高效:首部字段短**(8 bytes)**
  • 快速:可以突发式地传输

基于UDP的应用:

  • DNS:因特网目录服务,域名解析系统
  • SNMP:简单网络管理协议
  • 流媒体传输
  • 因特网电话

基于UDP协议,如何实现可靠传输?

  • 将可靠传输的机制放在应用层
  • 应用程序中定义差错控制的机制
UDP报文段结构
  • 提供差错检验: 检验和
  • 没有差错控制
  • 长度: 报文段的总长度
  • UDP检验和的计算:

3.4 可靠传输原理

不可靠信道的特点决定了可靠服务传输的复杂性
可靠数据传输:为上层实体提供的服务抽象是,数据可以通过一条可靠的信道进行传输。借助于可靠信道,传输比特就不会受到损坏或丢失。

  • 过程:
  • 逐渐引入问题,bit差错->分组丢失……
  • 发送端和接收端的协议逐渐丰富,版本演进
  • 工具:
  • 有限状态机(Finite State Machine, FSM)
  • 分别定义发送方和接收方的状态(行为)

rdt1.0理想信道中的数据传输
rdt2.x:处理信道中的bit差错
rdt3.0:处理信道中的bit差错分组丢失

rdt1.0:经完全可靠信道的可靠数据传输

  • 前提:下层信道是可靠的。底层信道没有bit差错、分组丢失
  • 发送端和接收端的有限状态机:发送端向底层信道发送数据,接收端从底层信道读取数据

rdt2.0:处理bit差错

  • 检测bit差错?差错检测:checksum()
  • 恢复bit差错?接收方反馈:
  • 肯定确认:接收方告诉发送方数据分组正确到达
  • 否定确认:接收方告诉发送方数据分组出错
  • 重传:发送方收到否定确认后重传该分组
  • rdt2.0的机制:停止等待协议(Automatic Repeat reQuest, ARQ)
  • 检测:接收方检测bit差错
  • 反馈:接收方发送确认消息(ACK或NAK)给发送方

rdt2.0存在的问题:当接收方的ACK/NAK信息出错时,可能导致接受方数据重复。
解决办法:识别重复的数据分组rdt2.1

rdt2.1:处理“混淆的确认”——为分组编号

  • 识别重复分组:为数据分组进行编号 - > 接收方丢弃重复分组 - > 重传肯定确认(ACK)

  • 序号空间最小为多少?理论上1个bit就够了,因为它可让接收方知道发送方是否正在重传前一个分组。

  • 发送端:

  • 为分组编号:两个编号 {0,1}足矣

  • 必须检测确认信息是否出错

  • 状态数量翻倍(相对于rdt2.0):在状态值中必须记录当前的数据分组号是0 还是 1。

  • 接收端:

  • 必须检测数据分组是否出错

  • 必须检测数据分组是否重复,状态值暗示了期待的分组号

rdt2.1存在的问题:接收方不知道最后的确认信息是否被发送方正确收到。

rdt2.2:小改进——不要否定确认(NAK)的协议

  • 和rdt2.1的功能相同
  • 只使用肯定确认(ACK),对ACK进行编号{0,1}足矣
  • 发送方收到重复编号的ACK等同于收到NAK,此时发送方将重传分组

rdt3.0:处理信道中的bit差错和分组丢失

  • 差错控制:检测、确认、重传
  • 处理分组丢失(如何让发送方认识到分组丢失了?):
  • 基于时间的重传机制:发送端设置“ 定时器 ” timer ,超时重发
  • 接收方仍然会收到重复分组:rdt2.2通过对分组编号能够处理冗余分组的情况

停止等待 - >流水线可靠数据传输协议

rdt3.0是一个停等协议,效率较低。
eg. 对于1Gbps的链路,有15ms的端到端时延,传输一个1KB的数据分组,链路的利用率有多少?吞吐率是多少?

  • 传输时延 = L/R = 8 kbit ÷ 109 bit/s =8 μs
  • 利用率=传输时延 / (往返时延+传输时延)
    =传输时延/(2 * 端到端时延+传输时延)
    =0.008÷(2 * 15+0.008)
    =0.00027
  • 意味着:每30ms传输1KB的数据,在1G的链路上只有33kB的吞吐量

流水线:发送方发送一个数据分组之后,在对方确认之前,可以继续发其他分组。

成倍地提高网络的通信效率
但需要考虑流水线中如何实现差错控制(分组丢失、损坏或延时后如何重传?)

  • 必须增加序号范围
  • 协议的发送方和接收方两端可能需要缓存多个分组(以备重传)
  • 所需序号范围和对缓存的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。
回退N步(GBN)/滑动窗口协议

发送方:

  • 允许发送方发送多个分组,而不需等待确认
  • 未确认的分组数 < N (窗口长度)
  • 发送方的缓存容量是有限度的
  • 不能让发送方“肆无忌惮”地发数据,否则跟UDP没太大区别
  • 流控制的需要:发送速率不能大于接收速率
  • 拥塞控制的需要:不要擅自给网络添堵
  • 发送方设置定时器:用于处理丢失重传问题
  • 定时器数目多多益善,但注意定时器也耗费资源!

接收方:

  • 接收方没有缓存(降低成本)
  • 只接收有序的分组(向上提交),会丢弃失序的分组
  • 接收方确认分组:
  • 分组丢失—数据失序 接收方丢弃失序分组
  • 确认丢失—累积确认 ack3 :小于等于序号3的分组都被确认收到
  • 分组出错—重复确认 接收方重复确认,发送方可在超时之前就重传

滑动窗口(slide window):窗口长度是固定的:N

选择重传SR

发送方:

  • 发送方有缓存(滑动窗口)
  • 允许发送方发送多个分组,而不需等待确认
  • 发送方有选择地重传:哪个分组的ack没收到,就重传那个分组

接收方:

  • 接收方有缓存(滑动窗口)
  • 分组失序:把分组缓存,向上层有序提交分组
  • 接收方确认分组:
  • 分组丢失—数据失序 接收方:缓存失序分组,逐个确认正确收到的分组
  • 确认丢失—超时事件 发送方重传
  • 分组出错—重复确认 接收方重复确认,发送方可在超时之前就重传(果断处之)

实现可靠传输的基础构件

  • 检验和
  • 定时器
  • 序号: 序号空间
  • 确认: 确认序号/累积确认/重复确认/逐一确认(/否定确认)
  • 窗口、流水线:窗口尺寸N、窗口变量:base, nextsqnum

    3.5 面向连接的运输:TCP

    TCP协议概述

  • 因特网中最复杂的协议之一
  • 端到端协议:一个发送方,一个接收方(不会广播)
  • 可靠传输:
  • 有序的字节流传输:无损坏、无间隔、非冗余、按序交付。(差错检验、重传、累积确认、定时器、序号、确认号)
  • 流水线协议:提供流控制和拥塞控制
  • TCP是全双工协议
  • 在一个TCP连接中,数据流是双向的,发送方/接收方 可以发送数据,也可以接收数据
  • MSS最大报文段长度:实际指报文段应用层数据的最大长度,不包括TCP首部长度。
  • TCP是面向连接的协议
  • 通过“握手”(交换控制信息),初始化发送方和接收方的状态
  • 连接状态完全保留在两个端系统中,TCP协议只在端系统中运行。中间的网络元素不会维持TCP的连接状态。P155
  • TCP可实现流控制
  • 发送方的发送速度不能超过接收方的接收速度

TCP可靠运输

TCP的序号、确认号
  • 序号空间:[0—232]
  • 序号规则:
  • 面向字节流编序号:报文段的编号是该报文段数据中第一个字节的编号
    Seq(i+1) == Seq(i) + Lsegment(i)
  • 不是对报文段编号
  • 确认号ACK:期望的下一个报文段
  • ACK(0) == 0
  • ACK(i) == Seq(i)+ 1
TCP的确认和重传机制
  • 流水线协议
  • GBN和SR的混合体
  • 此外,接收端也有定时器
事件 TCP接收方的动作
延迟确认 期望序号的报文段按序到达,之前的报文段都已经被确认 延迟500ms确认新到的分组(为累积确认做准备)
累积确认 期望序号的报文段按序到达,另一个按序报文等待确认 立即发送单个累积确认,确认两个按序报文段
冗余确认 比期望序号大的报文段到达。检测出间隔 立即发送冗余确认(重复确认),指示下一个期待字节的序号
立即确认 失序后最低望序号的报文段到达 立即发送确认(不延迟500ms)
快速重传 发送方收到3个冗余确认 超时之前重发报文段,避免无谓的等待
加倍超时 发送方产生一次超时重传 发送方加倍超时间隔。是一种有限形式的拥塞控制

累积确认还可以解决确认丢失的问题: 发送方不会重传分组

往返时间估计

TCP往返时间估计是为了解决TCP协议的发送方如何设置定时器的时间间隔的问题。
超时时间间隔应大于RTT(往返时间),但由于路由器的拥塞和端系统负载的变化,RTT总是在波动。

  • 超时时间间隔过小:累积确认到达之前,会产生不必要的重传!
  • 超时时间间隔过大:对分组丢失的反映迟钝,降低了传输效率。累积确认、快速重传可以解决一些问题,但还是需要充分估计RTT。

估计RTT
SampleRTT:某个报文段被发出,到收到确认的时间间隔。

TCP仅在某个时刻做一次SampleRTT测量,SampleRTT的值也会波动。因此需要统计学意义上的测量和估计

指数加权移动平均(EWMA) EstimatedRTT = ( 1 - α ) * EstimatedRTT + α * SampleRTT
RFC 6298: α = 0.125

估计RTT偏差 DevRTT = ( 1 - β ) * DevRTT + β * | SampleRTT - EstimatedRTT |
RFC 6298: β = 0.25

设置超时时间间隔 TimeoutInterval = EstimatedRTT + 4 * DevRTT

TCP报文段结构

  • 源端口和目的端口(各占 2 字节):是运输层与应用层的服务接口,实现对运输层的复用和分解。
  • 序号(4 字节):TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。
  • 确认号(4 字节):是期望收到对方的下一个报文段的数据的第一个字节的序号。
  • 数据偏移/首部长度( 4 bit ):指示了以32 bit(4 字节为计算单位)的字为单位的TCP首部长度。若无选项字段,TCP长度固定为20字节。
  • 保留字段( 6 bit ):保留为今后使用,目前均置为 0。
  • 6个比特位
  • URG 紧急比特位( 1 bit ):当 URG 为1时,告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。
  • ACK 确认比特位( 1 bit ):只有当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。
  • PSH 推送比特位( 1 bit ):接收推送比特位置 1 的报文段,接收方就应立即将数据交给上层,而不需缓存该报文段。
  • RST 复位比特位( 1 bit ):当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
  • SYN 同步比特位( 1 bit ):同步比特 SYN = 1,就表示这是一个连接请求或确认连接的报文段。
  • FIN 终止比特位( 1 bit ):用来释放一个连接。当FIN = 1 时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
  • 接收窗口( 2 字节 ):用于流量控制。TCP 连接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限
  • 检验和( 2 字节 ):检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
  • 紧急指针( 2 字节 ):紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。
  • 选项字段( 长度可变 ):目前只规定了一种选项,即最大报文段长度 MSS ;告诉对方 TCP“我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节。”
  • 填充字段( 长度可变 ):使整个首部长度是 4 字节的整数倍。

TCP流量控制

  • 目标:速度匹配 - > 发送速度不能大于接收速度
  • 原因:接收方的缓存空间有限,接收方提交数据的速度有限
  • 机制:
  • 接收窗口:接收缓存中的剩余空间
  • 接收方在向发送方确认时,随时告诉对方自己接收窗口的大小

TCP连接管理

TCP是“面向连接”的运输协议

  • 运输之前,要先建立“逻辑连接”
  • 初始化TCP的参数:序号、缓存
  • 客户端发起连接:Socket clientSocket = new Socket(“hostname”, “port#”);
  • 服务器端等待连接:Socket connectionSocket = welcomeSocket.accept();
  • 通过三次握手建立连接
  • 关闭连接

3.6 拥塞控制原理

网络拥塞

  • 通俗地讲:由于过多的端点高速发送大量的数据,导致网络(路由器)难以胜任数据的转发
  • 不同于流控制是匹配发送端和接收端的速度
  • 拥塞的表现:分组重传作为网络拥塞的征兆
  • 数据分组的丢失(路由器的缓存溢出)
  • 产生较长的时延(在路由器缓存排队)
  • 拥塞控制是网络中的关键问题

通过对异步传递方式(ATM)网络中可用比特率(ABR)服务中的拥塞控制的讨论来总结本节

拥塞情况1: 两个发送方和一台具有无限缓存的路由器

  • 链路的带宽:R
  • 没有重传、流控制和拥塞控制

拥塞情况2:两个发送方和一台具有有限缓存的路由器

  • 链路的带宽:R
  • 有分组重传控制:
    应用层:(初始数据)λin = (吞吐率)λout
    运输层:(供给载荷)λ´in ≥ λin (λ´in包括了重传的数据分组)

拥塞情况3 :四发送方和一台具有有限缓存的多台路由器和多条路径
新的拥塞代价: 一个路由器将分组丢失,这个路径上先前的路由器也做了无用功

理想情况 拥塞情况1 拥塞情况2
发送方”神知”路由器是否有可用缓存空间 路由器缓存溢出,丢失分组 路由器缓存中出现转发队列
只在路由器有缓存空间的情况下才发数据 发送方只在分组丢失的情况下重传 发送方产生超时事件
结果:不会丢失分组 λ´in = λ in 代价:发送方会重传丢失的分组 λ´in > λin 代价:发送方会重传延时的分组 λ´in > λin

吞吐量、时延与主机发送速率的函数关系

拥塞控制的方法

  • 端到端拥塞控制:
  • 网络层不提供显式拥塞反馈
  • 端点通过超时和冗余确认来感知是否发生了拥塞
  • 工作在运输层:通过TCP实现拥塞控制
  • 网络辅助的拥塞控制:
  • 路由器会告知端点产生了拥塞
  • 使用特殊的分组来告知阻塞
  • 工作在链路层

    3.7 TCP拥塞控制

  • 发送方感知网络的拥塞程度,来限制发送速度
  • 感知网络拥塞:发送方产生超时事件 / 收到接收方的3个冗余确认
  • 控制拥塞:发送方设计一个动态调节的“阀门”——拥塞窗口
拥塞窗口(cwnd)
  • 发送端的一个动态参数,用于控制发送速度,初始值为1MSS(最大报文段长度)
  • 拥塞窗口的工作机制
  • 限制向网络中传输的数据: LastByteSent-LastByteAcked ≤ cwnd
  • TCP传输速率也是动态的
    粗略地估计,在一个RTT内可以传输cwnd个字节: rate ≈ cwnd / RTT bytes/sec

拥塞窗口的动态调节策略

  • 在拥塞产生之前,保守地增加拥塞窗口的大小
  • `加性增`: 每次增加1MSS个字节,直到检测到丢包事件
    
  • 在感知到拥塞后,迅速地减小拥塞窗口的大小
  • 乘性减: 发生丢包事件后,拥塞窗口马上缩小一半

TCP拥塞控制算法
缓慢启动

  • 连接开始,速率翻倍提高,直到发生第一个丢包事件
  • 拥塞窗口初始值为1MSS
  • 每经历1RTT,拥塞窗口翻倍(*2)
  • 收到ACK后便进行更新
  • 初始速度很低,然后指数增长
  • 产生超时事件:拥塞窗口重设为1MSS,重新慢启动
  • 收到3个冗余确认:拥塞窗口减半,然后线性增长

拥塞避免(提前采取措施)

  • 设定一个门限(阈yù值)
  • 拥塞窗口达到门限值后,进入加性增长:每次增加1MSS
  • 产生丢包事件后,收缩窗口、阈值
  • 阈值:缩减为拥塞窗口的一半
  • 超时:拥塞窗口重新进入慢启动
  • 三个冗余ACK:拥塞窗口从新的阈值开始加性增加

快速恢复:TCP的可选功能。
TCP Tahoe:没有快速恢复,TCP Reno:综合了快速恢复

TCP拥塞控制算法(慢启动、拥塞避免和快速恢复)的完整FSM描述

TCP吞吐量的宏观描述
平均吞吐量是拥塞窗口和RTT的函数:
设W为丢包事件产生后的拥塞窗口大小,平均窗口大小约 3/4 W,平均吞吐量为3/4W per RTT
一条连接的平均吞吐量 = 0.75 * W / RTT
经高带宽路径的TCP吞吐量
网格和云计算需要高速的链路和吞吐量

eg. 1500Bytes报文段, 100ms RTT, 为了获得10 Gbps的吞吐率
设平均拥塞窗口W = 83,333Bytes
考虑到丢包情况的吞吐率, 设丢包率为L [Mathis 1997]:
一条连接的平均吞吐量 =

为了达到10Gbps的吞吐量,丢包率要非常低,小于L = 2·10-10!
针对高速的TCP设计,目前还在不断演化中

TCP的公平性

  • 公平性的目标:
  • 如果 K个TCP连接共享一个带宽为R的链路
  • 每个TCP连接拥有的平均传输率为 R/K
  • eg.设有两个相互竞争的连接,公平性的体现:两条连接实现的带宽最终将沿着平等带宽的共享曲线波动。它们最终会收敛该状态。
  • 公平性和UPD、公平性和并行TCP连接