计算机网络:传输层
传输层概述与UDP
传输层作用
为运行在不同主机上的进程之间提供逻辑通信,依赖网络层的服务
UDP和TCP差异比较
| 应用层需求 | 传输层服务 | UDP | TCP |
|---|---|---|---|
| 为运行在不同主机上的进程之间提供逻辑通信 | 进程间交付 | ✓ | ✓ |
| 检测报文段是否出错 | 差错检测 | ✓ | ✓ |
| 解决丢包、差错问题 | 可靠传输 | ✗ | ✓ |
| 解决乱序问题 | 按序交付 | ✗ | ✓ |
| 解决接收缓存溢出问题 | 流量控制 | ✗ | ✓ |
| 应对网络拥塞 | 拥塞控制 | ✗ | ✓ |
多路复用/多路分解
解决多个应用进程如何共享一条网络链路的问题
多路复用
把多个不同应用进程发出的数据,统一打包、封装成传输层报文段,通过同一个网络接口发送出去
如何判断哪个数据是哪个进程的呢? 依靠端口号和ip
- UDP:仅靠 目的端口号 即可
- TCP:需要 目的端口号 + 源端口号 + 源 IP + 目的 IP 四元组
多路分解
把从网络收到的混合报文段,根据目的端口号精准分发给对应的应用进程
套接字
-
UDP
一个套接字可以和多个套接字通信,由二元组<目的IP地址,目的端口号>识别,无连接
流程: 发送端: 创建UDP套接字 → 绑定端口(可选) → 调用sendto()发送数据(指定目的IP/端口) 接收端: 创建UDP套接字 → 绑定端口 → 调用recvfrom()接收数据(获取源IP/端口)
-
TCP
面向连接,必须靠「源 IP + 源端口 + 目的 IP + 目的端口」四元组唯一标识
流程: 服务端: 创建监听套接字 → 绑定端口 → 监听(listen) → 接受连接(accept,生成新的通信套接字) → 收发数据 → 关闭连接 客户端: 创建套接字 → 发起连接(connect,三次握手) → 收发数据 → 关闭连接(四次挥手)
四次挥手
通信双方:客户端 A,服务端 B
第一次挥手(A → B)A 发:FIN意思:我发完数据了,我要关我的发送通道
第二次挥手(B → A)B 发:ACK意思:收到你要关了,我知道了(但 B 可能还有数据要发,所以不能马上关)
第三次挥手(B → A)B 发:FIN意思:我也发完了,我也要关我的发送通道
第四次挥手(A → B)A 发:ACK意思:收到,你关吧
之后两边正式断开连接。
为什么比三次握手多一次? 因为B发ACK和FIN不是同时的,算两次。
UDP报文段结构

校验和
校验和作用是检测差错,但是检测到之后不重传,直接丢包
可靠传输
可靠传输基础:
- 解决差错问题
- 解决丢包问题
- 停等协议与流水线协议
- 滑动窗口协议
- 回退N步
- 选择重传
TCP可靠传输
解决差错问题
如何识别差错:
数据尾部添加校验码,接收方用同样的算法,重新算一遍校验码
无差错: 发送方:data1(无差错)->接收方:ack->发送方:data2(无差错)
有差错: 发送方:data1(有差错)->接收方:nck->发送方:data1(无差错)

ack有差错:(重传) 发送方:data1(无差错)->接收方:ack(有差错)->发送方:data1(无差错)
重传引发问题:接收方以为是新分组,但其实是冗余分组
解决方法:引入序号,数据有序号,发送带确认号的ACK(可代替nck)

解决丢包问题
怎么检测丢包?
- 解决方法:定时器机制
- 发送方等待足够的时间,如果还未收到ACK,则认定为丢包
- 如果定时器时长太短,误判丢包
- 如果定时器时长太长,等待时间就很长
丢包后怎么做?
重传
停等协议和流水线协议
停等协议
网络里只有一个未确认的分组
流水线协议
网络里有N个未确认的分组

信道利用率 (重点)
信道利用率 = 信道被占用的时间 / 周期
周期的本质是「从发第一个包,到收到第一个包的 ACK」的完整往返周期

滑动窗口协议
窗口:发送方维护“已发送但未确认”的序号集合,大小为 W;只有落在窗口内的序号才能发送(或重传)。 ACK:接收方对正确收到的数据返回确认;发送方收到 ACK 后把窗口向前滑动(左边界右移),右边界随之扩展,从而可以继续发新数据。 作用:在停等协议(发一帧等一 ACK)基础上,让链路上同时存在多个未确认分组,减少空闲时间,提高吞吐。
回退N步
接收方一般只按序接收;乱序或丢包时丢弃后续并重复 ACK 最近按序已正确接收的分组序号(最后一个按序 OK 的序号)。 发送方超时后从出错处起重传窗口内后续所有帧。 实现简单,但出错时重传浪费大。
选择重传
接收方:可以缓存乱序但已正确到达的分组,对每个正确收到的分组发 ACK(不必等“按序那一段”全齐才确认);只对缺失的分组在窗口内保留空位。 发送方:超时或根据 重复 ACK时,只重传丢失/出错的那一个(或少数几个)分组,而不是从出错点起把窗口里后面全重传一遍。
TCP
TCP报文段结构

- ACK比特:指示确认字段中的值有效
- SYN比特:用于建立连接
- FIN比特:用于拆除连接
流量控制(接收方)
解决的是:发送方别把接收方缓存“撑爆”
-
接收方在 ACK 里通过 TCP 首部“窗口”字段告诉发送方:自己还能再收多少字节
-
发送方的有效窗口 发送方在未确认数据量上受两个因素约束: EffectiveWindow = min(cwnd, rwnd) 其中 rwnd 是流量控制,cwnd 是拥塞控制;谁更小谁更“紧”。
-
滑动与更新 接收方应用读走数据 → 缓存空出 → rwnd 变大 → 通过后续 ACK 通知发送方 → 发送方可多发
-
rwnd = 0 表示“先别发了,缓存满了”。发送方会停发应用数据
拥塞控制(网络通路)
解决的是:别因为发太快把网络路由器队列塞满
1, 如何感知网络拥塞?
- 超时重传:发出去的数据长时间没收到 ACK,通常说明丢包严重,网络可能已经比较拥堵。
- 重复 ACK:连续收到多个重复 ACK,说明某个报文段可能丢了,但后续分组还能到,往往表示出现了轻度拥塞。
- RTT 变大:往返时延明显升高,常说明路由器排队变长,网络开始拥塞。
- ECN 标记:如果网络设备支持 ECN,路由器可以不丢包而是直接标记“快拥塞了”。
2, 如何限制发送速率?
受一个“窗口”限制:
- 拥塞窗口 cwnd:发送方根据网络状态维护的窗口,决定自己最多能有多少未确认数据在路上。
- 接收窗口 rwnd:接收方告诉发送方“我还能收多少”。
实际发送量通常受: 发送窗口 = min(cwnd, rwnd)
3, 如何动态调节发送速率?
核心思想就是:网络看起来没问题就慢慢加速;一旦怀疑拥塞就赶紧降速。
- 慢启动:刚开始发送时先保守,但增长较快,快速试探网络容量。
- 拥塞避免:到一定阈值后,改成较慢的线性增长,避免一下冲太猛。
- 检测到轻度拥塞(如 3 个重复 ACK):认为还能继续传,但要适当减小 cwnd,并快速重传丢失报文。
- 检测到严重拥塞(如超时):说明情况更糟,cwnd 大幅减小,重新进入慢启动。
吞吐量分析
单位时间内,实际成功传输了多少数据
常见单位:
bit/s Byte/s
影响吞吐量的主要因素
- 链路带宽:带宽越大,吞吐量上限越高
- RTT:往返时延越大,等待 ACK 越久,吞吐量越低
- 窗口大小:窗口越大,同时在路上的数据越多,吞吐量越高
- 丢包率:丢包会触发重传,降低有效吞吐量
- 协议机制:停等协议吞吐量低,流水线/滑动窗口吞吐量高