【计算机网络】第五章:传输层
本篇笔记课程来源:王道计算机考研 计算机网络
【计算机网络】第五章:传输层
- 一、传输层提供的服务
- 1. 传输层的功能
- 2. 传输层寻址与端口
- 二、UDP
- 1. UDP 协议
- 2. UDP 数据报
- 3. UDP 检验
- 三、TCP
- 1. TCP 协议
- 2. TCP 段
- 2. TCP 连接管理
- Ⅰ. 建立连接(三次握手)
- Ⅱ. 释放连接(四次挥手)
- 3. TCP 传输的底层原理
- Ⅰ. 传输过程
- Ⅱ. 发送缓冲区和接收缓冲区
- Ⅲ. 发送窗口和接收窗口
- 4. TCP 可靠传输
- 5. TCP 流量控制
- 6. TCP 拥塞控制
- 1. 概念
- 2. 慢开始算法
- 2. 拥塞避免算法
- 3. 快恢复算法
一、传输层提供的服务
1. 传输层的功能
- 传输层实现了 “端到端”(进程到进程)的通信。传输层在 TCP / UDP 报文段的首部,指明源端口、目的端口
- 复用和分用:
- 复用(从上到下):在发送数据的时候,同一台主机上的多个进程可以使用同一个传输层协议
- 分用(从下到上):在接收数据的时候,传输层可以把数据正确交付到目的进程
- 差错检测
- TCP 检测出差错后丢弃数据,并通知发送方重传
- UDP 检测出差错后直接丢弃数据,且不通知发送方
- 向应用层提供服务
- TCP 提供面向连接的、可靠的、面向字节流的端到端传输服务:
- 确保数据正确 / 完善,但开销大,实时性较差
- 面向连接:也可以叫有连接,传输前先打招呼,先确认对方已经准备好接收数据,传输结束时也要告诉对方已结束
- 可靠:接收方使用 “确认机制” 让发送方知道哪些数据已被正确接收
- 面向字节流:无论传输多少个报文,在 TCP 协议看来都是一连串字节流
- UDP 提供无连接的、不可靠的、面向报文的端到端传输服务:
- 数据可能出错 / 丢失,但速度快,开销小
- 无连接:不打招呼,直接把数据传给对方
- 不可靠:接收方无论收没收到数据、数据是否正确,都不给发送方反馈
- 面向报文:UDP 不能拆分数据报,只能传输整个数据报
- TCP 提供面向连接的、可靠的、面向字节流的端到端传输服务:
2. 传输层寻址与端口
- 通过端口号标识本主机的一个特定进程
- 每台主机的端口号是相互独立的
- TCP、UDP 两种协议的端口号是相互独立的
- TCP 或 UDP 协议,通过 Socket 套接字,唯一地标识网络中的一台主机上的一个应用进程
- 套接字(Socket)= {IP 地址:端口号}
- 本质上是一种数据结构,类似于网络指针,指向网络中将要和本进程通信的进程
- 当两个进程之间想要通信时,需要指明:
- 使用哪种传输层协议
- 本进程绑定的端口号
- 对方的 IP 地址和端口号
- 端口号的分类
- 服务器使用的端口号:被动通信
- 熟知端口号:
0~1023
,通常只能用于被熟知的重要应用程序应用程序 熟知端口号 功能 FTP 21 用于文件的上传、下载等文件传输控制。 TELNET 23 提供远程登录服务,可远程操控服务器。 SMTP 25 负责电子邮件的发送与传输。 DNS 53 将域名解析为对应的IP地址。 TFTP 69 进行简单的文件传输,协议简单开销小。 HTTP 80 用于万维网中网页数据的传输。 SNMP 161 监控网络设备状态,收集和管理设备信息。 - 登记端口号(不强制):1024 ~ 49151
- 熟知端口号:
- 客户端使用的端口号:主动通信
- 短暂端口号:49152 ~ 65535
- 服务器使用的端口号:被动通信
二、UDP
1. UDP 协议
- UDP(User Datagram Protocol,用户数据报协议):
- 是无连接的、不可靠的(可靠性可以交给应用层处理),也不支持拥塞控制
- 每次传输一个完整的报文,不支持报文自动拆分、重装,因此应用层的报文长度不能超过 UDP 协议上限
- 支持一对一(封装成单播 IP 数据报)、一对多(封装成广播 / 多播 IP 数据报)传输
- UDP 首部:首部很小,只占 8 B
2. UDP 数据报
- UDP 数据报包含首部和数据部分
- UDP首部占 8 B,包括:
- 16 位源端口号:发送进程的端口号,如果不需要对方回复置为全 0
- 16 位目的端口号:接收进程的端口号
- 16 位 UDP 长度:首部 + 数据的总长度,以 “字节” 为单位
- 16 位 UDP 校验和:由发送方的传输层计算并填入校验和,接收方的传输层检测是否有差错,如果无需校验置为全 0
- 数据部分:
- 传输层理论最大长度为 216−8=65535−8=655272^{16}-8=65535-8=65527216−8=65535−8=65527 B
- 网络层理论最大长度为 216−8−20=655072^{16}-8-20=65507216−8−20=65507 B
- 以太网最大长度为 1500−8−20=14721500-8-20=14721500−8−20=1472 B
3. UDP 检验
- 差错检验算法
- 计算校验和:将原始数据以 16 bit 为一组,进行二进制加法(最高位产生的进位需要 “回卷”),加法运算的最终结果逐位取反,得到 16 bit 校验和
- 差错校验:接收方将收到的内容以 16 bit 为一组,进行二进制加法(最高位产生的进位需要 “回卷”),全 1 说明没有差错,非全 1 说明有差错
- 发送方
- 在计算校验和之前,需要添加 12 B 的伪首部,计算完校验和之后,拆除伪首部
- 计算校验和时把首部的校验和临时填充为全 0,计算出来后再填入真正的校验和
- 把伪首部、首部、数据部分以 16 bit 为一组,计算计算校验和
- 长度和 UDP 长度相等,为整个 UDP 数据报的长度
- 接收方
- 在差错校验之前,需要添加 12 B 的伪首部,检验完之后,拆除伪首部
- 全 1 说明无差错,接收该 UDP 数据;非全 1 说明有差错,丢弃该 UDP 数据
三、TCP
1. TCP 协议
- TCP(Transmission Control Protocol,传输控制协议)
- TCP 协议支持报文拆分、重装,因此应用层的报文较长也是可以的
- TCP 协议的三大阶段
- 建立连接(三次握手)
- 数据传输
- 释放连接(四次挥手)
- 每次建立 TCP 连接,可以传输多个报文(双向),每个 TCP 段不会强制要求满载数据,只要别超过 MSS(Maximum Segment Size,最大段长)就行
- TCP 是面向字节流的,UDP 是面向报文的
2. TCP 段
- TCP 段(TCP Segment),也称为 TCP 报文段
- 源端口、目的端口:顾名思义,字面意思
- 序号(seq,sequence):
- 占 32 bit,用于标记数据部分第一个字节在原始字节流中的位置,可理解为偏移量
- 起始 “序号” 由发送方自己设置,不一定从 0 开始
- 确认号(ack、ack_seq):
- 占 32 bit,用于反馈,表示序号在该确认号之前的所有字节都已正确收到
- 具有 “累计确认” 的特性
- 标志位 ACK(大写)确认位:
- ACK = 0 时,确认号(ack_seq)无效
- ACK = 1 时,确认号(ack_seq)有效
- 只有 握手 ① 的 ACK = 0,其他所有 TCP 报文段 ACK = 1
- 数据偏移(Data Offset)
- 占 4 bit,表示 TCP 首部长度,以 ×4×4×4 B 为单位
- 因此 TCP 首部最长 =(24−1)×4=60=(2^4-1)×4=60=(24−1)×4=60 B
- 填充:因为数据偏移以 ×4×4×4 B 为单位,因此该部分用于凑足 4 B 的整数倍
- 保留:占 6 bit,暂时没用,通常全部置为 0
- 标志位 URG(Urgent):紧急位
- URG = 1 时,紧急指针有效。表示这是紧急数据,应尽快插队发送
- 紧急指针:
- 占 16 bit,紧急数据专用序号,原理上与 “序号”(seq)字段相同
- 紧急数据有一套独立的序号,普通数据是另外一种序号
- 标志位 PSH(Push):推送位
- PSH = 1 时,表示希望接收方尽快回复(用于交互式通信)
- 标志位 RST(Reset)复位位:
- RST = 1 时,表示出现严重差错(如主机崩溃),必须释放连接
- 也可用于拒绝一个非法报文段(如恶意的黑客攻击)
- 标志位 SYN(Synchronize)同步位:
- SYN = 1 时,表示这是一个连接请求或连接接受报文。
- 只有 握手 ①、握手 ② 的 SYN = 1,其他所有 TCP 报文段都是 SYN = 0
- 标志位 FIN(Finish)终止位:
- FIN = 1 时,表示此报文段的发送方的数据已发送完毕,要求释放传输连接
- 只有 挥手 ①、挥手 ③ 的 FIN = 1,其他所有的 TCP 报文段都是 FIN = 0
- 窗口(rwnd、rcvwnd,Receive Window):
- 占 16 bit,表示接收窗口的大小。即从本报文段首部中的 ack_seq 算起,接收方还能接收多少数据(以字节位单位)
- 窗口字段是实现流量控制的关键
- 检验和
- 占 16 bit,原理与 UDP 雷同,计算校验和之前也需要添加 12 B 的伪首部
- TCP 的协议号是 6,UDP 的协议号是 17。(看 UDP 的数据报图)
- 伪首部的长度为整个 TCP 段(首部 + 数据)的长度
- 选项:
- 长度可变,可以为空,也可以非空
- 建立 TCP 连接时,在握手 ①、握手 ② 选项中协商 MSS(Maximum Segment Size,最大段长)
- MSS 的值表示在接下来的数据传输中,一个 TCP 报文段最多携带多少数据(首部不算在内)
- 通常 MSS 不会设置太大,以免在 IP 层被分片
2. TCP 连接管理
Ⅰ. 建立连接(三次握手)
- 起始序号由客户进程或服务器进程自己决定
- 标志位:
- 在 TCP 全过程中,只有握手 ①、握手 ② 的 SYN = 1,其他所有 TCP 报文段都是 SYN = 0
- 在 TCP 全过程中,只有握手 ① 的 ACK = 0,其他所有 TCP 报文段都是 ACK = 1
- 携带数据:
- 握手 ①、握手 ② 不能携带数据(只有 TCP 首部),但是仍要消耗一个序号
- 握手 ③ 不携带数据就不消耗序号,如果携带 100 B 数据就消耗 100 个序号
- TCP 状态转换
- 客户进程:连接关闭(CLOSE)、同步已发送(SYN-SENT)、已建立连接(ESTABLISHED)
- 服务器进程:连接关闭、监听 / 等待连接(LISTEN)、同步已收到(SYN-RCVD)、已建立连接
- 客户收到握手 ② 就可以开始传送数据,服务器收到握手 ③ 才能传送数据
- 建立连接耗时分析:
- 客户端发出握手 ① 后,客户端至少需要 1×RTT1 ×RTT1×RTT 可以发送数据,服务器至少需要 1.5×RTT1.5× RTT1.5×RTT 可以发送数据
Ⅱ. 释放连接(四次挥手)
- 标志位:
- 所有挥手的 SYN = 0、ACK = 1
- 在 TCP 全过程中,只有挥手 ①、挥手 ③ 的 FIN = 1,其他所有 TCP 报文段都是 FIN = 0
- 携带数据
- 挥手 ①、挥手 ③ 即使不携带数据,也要消耗一个序号
- 挥手 ② 可以携带数据
- 挥手 ④ 不可以携带数据
- TCP 状态转换
- 客户进程:已建立连接(ESTABLISHED)、终止等待 1(FIN-WAIT 1)、终止等待 2(FIN-WAIT 2)、时间等待(TIME-WAIT)、关闭(CLOSE)
- 服务器进程:已建立连接、关闭等待(CLOSE-WAIT)、最后确认(LAST-ACK)、关闭
- 任一进程在接收到挥手 ③ 后立即进入 “时间等待” 状突,并启动 “时间等待计时器”,倒计时 2 MSL 才能进入关闭状态
- MSL:最长报文段寿命,Maximum Segment Lifetime,是由 TCP 协议规定的一个固定时间长度
- 如果等待期间重复收到挥手 ③,就重置计时器
- 释放连接耗时分析
- 如果服务器进程收到挥手 ① 时,已经没有待传送数据,那么可以连续发出挥手 ②、挥手 ③
- 客户端发出挥手 ① 后,客户进程至少需要 1×RTT+2×MSL1×RTT+2×MSL1×RTT+2×MSL 进入关闭状态;服务器进程至少需要 1.5×RTT1.5×RTT1.5×RTT 进入关闭状态
3. TCP 传输的底层原理
Ⅰ. 传输过程
- 重点关注:ACK、seq、ack(ack_seq)、rwnd(rcvwnd)
- 应用层运行在用户区,传输层运行在内核区,因此需要使用系统调用将进程绑定到端口,让操作系统的 TCP 协议根据 Socket(套接字)对象向接收方发出 TCP 报文段
- 应用层中的待发送数据和待接收数据本支持是一个
char
型数组,数组若与预留长度不够可以再扩容
- 一个端口可以支持多个 TCP 连接,但每个 TCP 连接仅支持一对一通信(全双工)
- 全部传输过程如下图:
Ⅱ. 发送缓冲区和接收缓冲区
- 缓冲区是操作系统给此次 TCP 连接分配的
char
型数组 - TCP 协议支持双向传输,因此无论是客户进程还是服务器进程都拥有各自的发送缓冲区和接收缓冲区,缓冲区分配多少取决于操作系统内核
- TCP 协议的发送缓冲区、接收缓冲区是在建立连接时由操作系统内核分配的,大小不固定
- 接收缓冲区若只要保证数据有序,就可以按序交付应用层(给应用层复制一份),并清空缓冲区
Ⅲ. 发送窗口和接收窗口
- 发送窗口的大小不能超过发送缓冲区的大小Size发送窗口≤Size发送缓冲区Size_{发送窗口}≤Size_{发送缓冲区}Size发送窗口≤Size发送缓冲区
- 发送窗口的大小不能超过对方的接收窗口大小Size发送窗口≤Size接收方接收窗口大小Size_{发送窗口}≤Size_{接收方接收窗口大小}Size发送窗口≤Size接收方接收窗口大小
- 接收窗口根据 rwnd 的值动态调整窗口大小
4. TCP 可靠传输
- TCP 依靠 序号、确认机制、重传机制 实现可靠传输
- 序号:进程在建立连接时确定起始序号,数据传输过程中,每个字节对应一个序号
- 确认机制和重传机制在数据链路层也有,数据链路层是以帧为单位,TCP 是以报文段为单位
- 确认机制:
- 累积确认规则:如果收到 ack_seq=nack\_seq = nack_seq=n,说明序号在 nnn 之前的所有字节都已正确接收
- 两种 ACK 段:
- 专门确认:一个 ACK 段只有 TCP 首部,而没有携带数据
- 捎带确认:一个 ACK 段顺道携带了数据
- 专门确认:一个 ACK 段只有 TCP 首部,而没有携带数据
- 返回 ACK 的时机 —— 推迟确认:
- 推迟时间最多不能超过 0.5 秒(TCP 标准规定)
- 如果自己也有数据要传送给对方,就不推迟了,立即返回 ACK 段,并 “捎带” 自己的数据
- 若连续收到两个长度为 MSS 的报文段,就立即返回 ACK 段,因为重传代价高
- 推迟确认能发挥累计确认的特性,但当某个报文段传输出现问题都可能导致几个报文段陆续超时,导致重传重复报文段
- 重传机制
- 超时重传:每发出一个报文段,就设置一个计时器,若计时器到期还没收到确认,就重传这一报文段,并重置计时器;收到 ACK 段后终止计时器
- 快重传(冗余 ACK) —— 立即确认:
- 作用:让可能出错的报文段尽早重传,而不是非要等到超时再重传
- 每收到一个 TCP 报文段,就立即返回一个 ACK 段
- 即使收到一个失序报文段,也要立即返回 ACK 段(失序报文段会导致冗余 ACK)
- 当发送方连续收到 1 + 3 个确认号相同的 ACK(后三个属于冗余 ACK)时,就立即重传该确认号对应的报文段
- 超时重传:每发出一个报文段,就设置一个计时器,若计时器到期还没收到确认,就重传这一报文段,并重置计时器;收到 ACK 段后终止计时器
5. TCP 流量控制
- TCP 依靠 滑动窗口机制 实现流量控制:通过接收方的接收窗口大小限制发送方的发送窗口大小,这样就实现了由接收方控制发送方发送数据的速度
- 接收方维持一个接收窗口(记为 rwnd 或 rcvwnd):
- 接收窗口不能大于接收缓冲区大小
- 接收窗口 “框住” 的是接收方还允许接收的序号范围
- 发送方为一个发送窗口
- 发送窗口不能大于发送缓冲区大小
- 发送窗口不能大于接收方的接收窗口大小
- 发送窗口 “框住” 的是发送缓冲区中,已发送但尚未收到确认的数据,以及可以发送但尚未发送的数据
6. TCP 拥塞控制
1. 概念
- 拥塞(congestion)、拥塞窗口(cwnd)、拥塞控制阈值(ssthresh)
- 拥塞控制和流量控制的区别:
- 流量控制:控制 端到端 的数据发送量,是 “局部的”
- 拥塞控制:控制 整个网络 中每台主机的数据发送量,降低路由器负载,是 “全局的”
- 如何判断网络拥塞
- 不拥塞 —— 发出的每个报文段,都能顺利地收到 ACK 确认
- 严重拥塞 —— 发出的报文段未能按时收到 ACK,引发超时重传。此时应迅速缩小拥塞窗口
- 有点拥塞 —— 收到冗余 ACK,引发快重传。此时应适当缩小拥塞窗口
- 检测到网络拥塞怎么办
- 迅速减少发送的数据量,发送窗口的上限值 =
min[rwnd,cwnd]
- 拥塞窗口 cwnd 的大小常以 “MSS 的倍数” 作为单位
- 迅速减少发送的数据量,发送窗口的上限值 =
2. 慢开始算法
- 用于严重拥塞时,迅速缩小 cwnd
- 慢开始算法:cwnd 值从 1 开始,每收到一个 ACK,就让 cwnd + 1(当
cwnd < ssthresh
时适用)
- 如果发生超时重传(说明严重拥塞),使用慢开始算法迅速缩小 cwnd
- 缩小规则:ssthresh 值置为当前拥塞窗口的一半,且不能小于 2。同时将 cwnd 缩小到 1
ssthresh=cwnd/2=12\text{ssthresh}= \text{cwnd} / 2 = 12ssthresh=cwnd/2=12
cwnd=1\text{cwnd}=1cwnd=1 - 缩小规则:ssthresh 值置为当前拥塞窗口的一半,且不能小于 2。同时将 cwnd 缩小到 1
2. 拥塞避免算法
- 用于不拥塞时,小心地调大 cwnd
- 拥塞避免算法:在一个 RTT 内,即使收到多个 ACK,也只能让 cwnd + 1(当
cwnd ≥ ssthresh
时适用)
3. 快恢复算法
- 用于有点拥塞时,适当缩小 cwnd
- 快恢复算法:一旦发生快重传,就将阈值 ssthresh、cwnd 都设为当前 cwnd 的一半(ssthresh 不能小于 2),然后切换到拥塞避免算法