5.1 运输层概述
5.1.1 基础知识补充
从 IP 层来说,通讯主体是两台主机。但从运输层的视角来看,真正进行通信的实体一台主机中的一个进程与另一台主机一个的进程。
因此,运输层有一个比较重要的功能——复用 (multiplexing) 和分用 (demultiplexing)。复用是指发送端不同应用程序可以使用同一个运输层传输协议。
由图观之,网络层为主机之间提供逻辑通信,而运输层为进程之间提供逻辑通信。
5.1.2 运输层的端口
单个计算机用的是进程标识符,但由于计算机操作系统种类很多,因此使用该种进程标识符来表示进程并不合适。
此外,由于进程创建撤销均是动态的,通信一方几乎无法识别对方机器上的进程,因而将特定进程指名为终点是不可行的。
解决方案是运输层采用协议端口号 (protocol port number),或简称为端口 (port)。这种抽象的协议端口是软件端口。端口号只具有本地意义,只是为了标志本计算机应用层中的各个进程在运输层交互时的层间接口。不同计算机相同端口号是没有关联的。
运输层端口号分为两大类:
- 服务器端使用的端口号:又分为两种
- 熟知端口号:又称系统端口号。
- 系统端口号:又称短暂端口号,通信结束就回收可给其它进程使用。
5.1.3 运输层两个协议
用户数据报协议 UDP (User Datagram Protocol):传输前无需建立连接,不提供可靠交付,且较为简单。
传输控制协议 TCP (Transmission Control Protocol):提供面向连接的服务,但不提供广播或多播服务,较为复杂。
接下来将详细阐述两个协议的内容及要点。
5.2 用户数据报协议 UDP
UDP 有主要特点如:
- UDP 是无连接的。
- UDP 使用尽最大努力的交付。
- UDP 是面向报文的。直接将来自应用程序的报文添加首部后即交付 IP 层,因此报文大小的缺点需由应用程序负责。
- UDP 无拥塞控制。
- UDP 支持一对一、一对多、多对一和多对多交互通信。
- UDP 首部开销小,止 8 字节。
首部格式如图:
若接收方发现收到端口号不正确,则丢弃并由网际控制报文协议 ICMP 发送”端口不可达“差错报文。
”伪首部“的出现是为了计算检验和,在实际传输中并不存在。检验和为 UDP 数据报每一个 16 位字之和的反码,到接收端再与每一 16 位字相加,最终结果为全 1 即无差错。
5.3 传输控制协议 TCP 概述
5.3.1 TCP 协议主要特点
- 面向连接,使用前建立连接,使用后释放连接。
- 只能是点对点的通信。
- 提供可靠交付,无差错,不丢失,不重复,且按序到达。
- 提供全双工通信。
- 面向字节流。流是指流入到进程或从进程流出的字节序列。
5.3.2 TCP 的连接
TCP 连接的端点叫套接字 (socket) 或插口,我们由:
5.4 可靠传输工作原理
理想传输条件两大特点:
- 传输信道不产生差错。
- 不论发送端以多快速度发送数据,接收端总来得及处理收到数据。
5.4.1 停止等待协议
假定 A 与 B 之间进行通讯。
5.4.1.1 无差错情况
无差错时,A 发予 B 一个分组,B 接受后对 A 发送该分组的确认,A 收到确认后继续发送下一分组,如此往复。
5.4.1.2 出现差错
B 接受到分组时除了差错并丢弃,或是分组在传输中丢失,B 都不会发送任何消息。A 过了一段时间没收到确认,就执行超时重传。为实现超时重传,每发送一个分组设置一个超时计时器。若计时器到期前收到确认,则撤销计时器。
- A 发送完分组必须保存副本以备重传。
- 分组与确认分组必须编号。
- 重传时间应稍大于平均往返时间,提升效率节省资源。
5.4.1.3 确认丢失与确认迟到
倘如 B 接收到分组 $M_1$,但发回 A 的确认丢失,A 执行重传,B 又收到了相同的分组,此时应作两个动作:
- 丢弃重复分组。
- 向 A 发送确认。
这种可靠传输协议通常称自动重传请求 ARQ (Automatic Repeat reQuest)。
重传协议的优点是简单,但缺点是信道利用率低。
为了提高传输效率,我们采用流水线传输。为此引出下面一堆芝士。
5.4.2 连续 ARQ 协议
核心概念是窗口,窗口大小设定为 size。
每次,发送端将窗口内连续的分组全部发送出去,接收端采用累计确认方式,对按序到达的最后一个分组发送确认。发送端每收到一个确认,就进行调整把滑动窗口前移。
5.5 TCP 报文段首部格式
- 确认号:期望收到下一个报文段的第一个数据字节的序号。
若确认号 = N,则表明:到序号 N-1 为止所有的数据都已经收到。
- 紧急 URG (URGent):置为 1 时,紧急指针字段有效,应尽快传送。
- 确认 ACK (ACKnowledgment):置为 1 时确认号才有效。TCP 规定建立连接后所有报文段 ACK 都必须置为 1。
- 同步 SYN (SYNchronization):置为 1 表示是一个连接请求或连接接受报文。
- 窗口:接收方让发送方设置其发送窗口的依据。窗口字段指出了现在允许对方发送的数据量。窗口值经常动态变化着。
- 紧急指针:指出紧急数据字节数。
- 选项
- TCP 最初只规定一种选项,最大报文长度 MSS (Maximum Segment Size),指的是每一个 TCP 报文段数据字段最大长度,默认值为 536 字节。
- 后续增加窗口扩大选项,TCP 首部窗口是 16 位,窗口扩大选项占 3 字节,其中一个字节表示移位值 S,位数从 16 增大到 (16 + S),且 S 最大值为 14。无需扩大时,可以发送 S = 0 的选项。
- 时间戳,一是用于计算往返时间 RTT,二是处理 TCP 序号溢出的情况。
5.6 TCP 可靠传输的实现
5.6.1 补充
TCP 滑动窗口也有可能后缩,但 TCP 标准墙裂不推荐这么做。重传机制已如上讲述。
发送缓存暂时存放:
- 发送程序传送给发送方 TCP 准备发送的数据;
- TCP 已发送但未收到确认的数据。
接收缓存暂时存放:
- 按序到达但尚未被接收程序读取的数据;
- 未按序到达的数据。
对于未按序到达的数据,TCP 标注并无明确规定如何处理。一般是待缺失的数据流收到后,再按序交付上层。
5.6.2 超时重传时间的选择
采用自适应算法。RTT:往返时间。RTO:超时重传时间。
Karn 算法及修正:计算加权 RTTS 时,不考虑重传段。每重传一次,将 RTO 加倍。
5.7 TCP 流量控制
流量控制就是让发送方发送速率不要太快,让接收方来得及接收。
发送方的窗口不能超过接收方给出的接收窗口的数值。
若 B 向 A 发送零窗口后, 又有了存储空间,继续发送 rwnd = 400 的报文段,却于传输途中丢失,A 一直等待 B 的通知,而 B 也一直等待 A 的报文段,若没有其它措施,死锁局面将一直持续下去。为此,TCP 为每个连接设有一个持续计时器 (persistence timer)。只要一方收到对方零窗口通知则启动计时器,时间到期则发送零窗口探测报文段(仅携带 1 字节数据)。若窗口值确实为 0,就重置,否则死锁局面被打破。
TCP 的实现广泛使用 Nagle 算法:若进程把数据逐字节发送到 TCP 缓存,则发送方把第一个数据字节先发送出去,把后面到达的全部缓存。当收到第一个数据字符确认后,再把缓存中所有数据组装成一个报文发送出去,对随后到达的数据缓存。仅当收到前一个段的确认后才发送下一个段。当到达数据已经到达发送窗口大小一般或最大报文长度,就立即发送。 这种算法可以有效提高网络吞吐量。
窗口糊涂综合征:TCP 接收方缓存已满,而交互式应用进程每次只从接收缓存中读取 1 字节。接收方发回确认,将窗口置位 1 字节。如此下去,效率很低。为解决此问题,可以让接收方等待一段时间,待缓存能容纳一个最长报文段或有一半闲余空间,发出确认报文,并通知当前窗口大小。
5.8 TCP 拥塞控制
5.8.1 拥塞控制一般原理
拥塞控制即防止过多数据注入到网络中,可以使网络中路由器或链路不至过载。
拥塞控制分为开环控制与闭环控制两种。开环控制是在设计网络时事先将有关发生拥塞的因素考虑到,但系统运行后就不做改变了。
闭环控制基于环路反馈,有如下措施:
- 检测网络系统以定位拥塞。
- 将拥塞信息传送到可采取行动的地方。
- 调整网络系统运行以解决问题。
5.8.2 拥塞控制方法
慢开始、拥塞避免、快重传、快恢复四种算法。
- 慢开始:发送方维护一个拥塞窗口 cwnd (congestion winodw) 变量,发送时发送窗口等于拥塞窗口。以超时为依据判断网络拥塞,自小到大采用倍增增大拥塞窗口。
用报文段个数作为窗口大小单位,每经过一个传输轮次,cwnd 加倍。SMSS (Sender Maximum Segment Size) 是指发送方的最大报文段。
- 拥塞避免算法:每经过一个 RTT 就让 cwnd 加 1,呈线性缓慢增长。
实际操作中,慢开始和拥塞避免是配合使用的。设定一个 ssthresh 值,cwnd 小于该值,用慢启动;cwnd 大于该值,用拥塞避免;等于二者均可。
超时则门限值置为当前 cwnd 的一半。当 B 端收到无序帧时,仍然发送对最前端已确认帧的确认,当 A 端收到一连三个确认帧,即可视为发生了数据丢失。
快恢复算法:发送端得知丢失个别报文段,便不进行慢启动,二是置拥塞窗口 sstresh = cwnd = cwnd / 2,并执行拥塞避免算法。
拥塞避免阶段窗口线性增大,称为加法增大 AI (Additive Increase)。出现拥塞将门限值调整为原来一半,称为乘法减小 MD (Multiplicative Decrease)。二者结合即 AIMD 算法。
同时发送窗口不得超过接收端窗口上限 rwnd。故有:
5.8.3 主动队列管理 AQM
路由器队列管理通常按照先进先出 FIFO 规则处理到来数据,当队列满时丢弃后续到达所有分组,称为尾部丢弃策略。但这种做法会导致短时间内大量连接同时进入满开始阶段,称为全局同步 (global syncronization)。
为避免这种情况。出现了主动队列管理 AQM (Active Queue Management),当队列长度达到某个警惕值时丢弃到达分组。曾流行的实现方法是随即早期检测 RED (Random Early Detection),描述如下:
- 若平均队列长小于最小门限,则将新分组加入队列。
- 若超过最大门限,则丢弃新分组。
- 若介于二者之间,则按某一丢弃概率 p 将新分组丢弃。
5.9 TCP 运输连接管理
主动发起连接的进程称为客户 (client),被动等待连接的进程称为服务器 (sever)。
5.9.1 TCP 连接的建立
三次握手协议:(来自亲爱的 ChatGPT)
- 第一步 - 客户端发送连接请求:
- 客户端首先向服务器发送一个TCP报文,标志位中设置了SYN(同步)标志,并选择一个初始序列号(Initial Sequence Number)。
- 这个报文包含了客户端的一些连接参数,如MSS(Maximum Segment Size),表示客户端能够接受的最大报文段大小。
- 第二步 - 服务器确认请求并发送自己的连接请求:
- 服务器接收到客户端的SYN报文后,会回复一个确认报文,其中设置了SYN和ACK(确认)标志。
- 服务器也会选择一个自己的初始序列号,并在确认中包含自己的一些连接参数,如MSS。
- 第三步 - 客户端确认服务器的连接请求:
- 客户端接收到服务器的确认后,会向服务器发送一个确认报文,其中设置了ACK标志。
- 这个确认报文不包含SYN标志,因为连接已经建立。
- 服务器收到这个确认后,连接建立完成。
5.9.2 TCP 连接释放
- A 的进程线向其 TCP 发出连接释放报文段,并停止发送数据,主动关闭 TCP 连接。FIN 报文消耗一个序号,即使不携带数据。
- B 收到报文段后立即发出确认,确认号 ack = u + 1,从 A 到 B 的连接即释放了,但从 B 到 A 的连接仍未释放,TCP 处于半关闭状态。
- 若 B 依据没有要向 A 发送数据,则发出释放报文,假定序号为 w。A 收到后,必须发出确认,ack = w + 1,序号为 seq = u + 1,经过等待计时器设置的时间 2MSL 后, A 进入 CLOSED 状态。,MSL 是最长报文段寿命。
此外,TCP 设有一个保活计时器,每个一段时间发送探测字段,若一连几个都收不到回应,则关闭连接。