«计算机网络»笔记:第6章 传输层
6.1 传输服务
为什么需要传输层:
-
IP 包不可靠
-
IP 包大小有限
-
IP 无法区分应用程序
功能:
-
提供高效,可靠,高效的数据传输服务
-
进程到进程。
-
提供多个 SAP
C/S 模型
服务器:管理资源,被动接受请求
客户端:主动发送请求
通信流程:
寻址:端口号
作为服务访问点。位于传输层包头。
复用
不同的端口可以使用同一个底层接口。
SCTP:让一个连接可以多个接口传输,例如同时用 Wifi 和以太网传输。
差错控制:自动请求重传、滑动窗口
缓存策略:
-
固定缓存
-
动态缓存链表
-
大型缓存
Max-Min Fairness
基本含义:使得资源分配向量的最小分量的值最大,防止任何网络流被“饿死’,同时在一定程度上尽可能增加每个流的速率。
原则:一个信道上,在满足最小需求的前提下,各流尽量均分带宽;
如果增加任何一个参与者(分量)的带宽,将导致其它的具有相同或者更少带宽的参与者(分量)的带宽下降,说明此时即满足了最大最小公平性。
收敛性:尽快达到理想分配
例子:假设某互联网公司净利润120万元,有员工 A,B,C,D 和老板 E,F,员工觉得自己至少应该分到 12 万,老板觉得给了你们工作已经是你们的福报了,你们每人六万,剩下归我和我老婆。也即需求分别是:12, 12, 12, 12, 48, 48.
结果社会主义改造来了。
第一轮:先平均分,120/6=20, 每人分到 20 万,但是员工的需求只有 12 万:
A B C D E F
12 12 12 12 20 20
多出来 8x4=32 均分给老板:20+16 20+16 = 36:
A B C D E F
12 12 12 12 36 36
这样员工满意了。
6.2 传输层协议基础
6.3 拥塞控制
拥塞控制
-
发现拥塞
-
通知源主机、或隐式通知(源主机自己判断)
-
源主机动态调节速率
源主机如何动态调整带宽
AIAD 方式:线性增减。
MIMD 方式:指数增减。
这两种会反复震荡,难以收敛。
AMID 方式:线性增长,指数减少,容易收敛。
实际做法:调整窗口大小。
6.4 UDP
DNS、SNMP、DHCP、RIP、RTP 使用 UDP。
-
无连接,不可靠
-
简单高效
-
基于 IP 的复用、减复用
数据包格式:
校验和是整个数据(伪报头,报头,数据),可选。保留消息边界。
伪报头:只用于校验和,不传输。传输的时候去掉 Padding。
6.5 TCP 传输控制协议
-
面向连接
-
可靠传递(ARQ,自动请求重传)
-
ACK
-
校验和
-
超时重传
-
序列号
-
滑动窗口流控
-
-
拥塞控制
-
字节流,不保留消息边界(应用层自己判断)
TCP 报文段
单位 4B。
MSS:最大段长度,是报文最大数据长度。
滑动窗口大小可变,用于流量控制。
端口号各两字节。
序号:第一个数据字节的编号。32bit。
确认序号:准备接收的下一个字节的编号。32bit。
TCP 头长:4字节为单位。
窗口大小:接收方告诉发送方的限制字节数。
校验和:伪报头+整个报文段
注意序号不是单个递增,而是根据收到的字节数递增。
控制字段
URG:紧急数据,例如中断信号。配合紧急数据指针(Urgent pointer)使用,指向紧急数据的末尾。
PSH:立即发送数据。避免等待。
SYN:同步序列号
ACK:ACK 字段有效
FIN:断开连接
ECE,CWR
ECN:拥塞通知
ECE:通知有拥塞
CWR:报告收到了拥塞通知
SACK(选择性 ACK),最多能同时确认三段范围。用于选择重传。
TCP 连接的建立
两端:
-
服务器:被动方
-
客户端:主动方
-
第一次握手:客户端提出建立请求,设置控制位 SYN=1,并携带数据的起始序号 seq:x
-
第二次握手:服务端响应连接,设置控制位 SYN=1, ACK=1, 并携带数据的起始序号(服务器发送序号)seq: y, 确认序号:ack: x+1(因为第一步消耗一个序号)
-
第三次握手:客户端确认,设置控制位 ACK=1,发送序号 seq: x+1,确认序号 ack: y+1(第二步也消耗一个序号)
sequenceDiagram
participant client
note right of server: tcp三次握手
client ->> server: syn=1
server -->> client: syn+ack
client ->> server: ack
note right of server: tcp四次挥手
client ->> server: fin
server -->> client: ack
loop
server -->> server: server handle left data
end
server -->> client: fin
client ->> server: ack
(a):常规情况
(b):对等通信(不考虑 Client、Server 区分)的情况,两边同时建立连接。这种情况,双方约定的起始序号一样(x+1, y+1),所以不会导致建立两个连接的错误。
起始序号的确定:根据当前时钟参照
崩溃之后尚在网上的数据:
通过 MSL(最大段生命期)机制,超过一定时间就销毁包,防止主机挂掉之后,包仍然在网上游荡。
数据传输阶段
例子:
客户端连续发送两个报文段,序号分别是 8001, 9001,大小为 1000B
服务器进行累计确认,ack: 10001。seq’: 15001,大小为 2000B
客户端:确认,2000B,ack: 17001,rwnd: 10000,设置窗口字节大小
TCP 连接释放
客户端释放:
-
客户端设置 FIN=1, seq: x
-
服务器设置 FIN=1, ACK=1,ack: x+1,seq: y(第一步消耗一个字节序号)
-
客户端设置 ACK=1,seq: x+1, ack: y+1(第二步消耗一个字节的序号)
四步释放-半关闭连接:
-
客户端释放请求 FIN=1, seq: x, ACK=1
-
服务器还没发完,所以只释放 C->S 方向。所以只回应 ACK=1。seq: y, ack: x+1.
-
服务器继续发送数据,客户端回 ACK
-
服务器发完了,可以关闭了。seq: z, ack: x+1, ACK=1, FIN=1
-
客户端释放接收缓存,seq: x+1, ack: z+1, ACK=1
流控和滑动窗口
通过 WIN 字段通知自己的窗口剩余。当收到 WIN=0 可知对方窗口空了。之后再次收到 WIN > 0(窗口更新通知),可知可以继续发送了。
当窗口为 0 时:
-
正常分片不能发
-
紧急数据可以发
-
可以定时重发 1B 报文,通知对方继续工作(防止互相等待,死锁)
实际窗口大小:
-
受限于接收方窗口
-
受限于拥塞状况
Nagle’s 攒一攒算法
解决效率低下(Overhead:TCP head + IP head = 40B)
发送方用 Nagle 算法改进效率:
-
积攒到 MSS 的一半再发
-
上一分片的 ACK 已经收到了,那么还是得发,不能让对方等着
Clark 方法
解决接收方窗口更新量太少(Silly Window Syndrome)
- 接收方就不要通知窗口更新了,除非自己的缓存达到 MSS 或者缓存的一半。
差错控制
ARQ:
-
Checksum
-
ACK
-
超时重发(RTO,重传超时时间)
累计 ACK:多等一会儿,没有多的包了,再进行确认。
快速重传:发送方连续收到几个相同的 ACK,这时提前重传那个 ACK 对应的报文,而不是等超时再重传。
数据破坏:TCP 采用的方案是不回任何信息,让对方超时重传。
ACK 丢失:由于采用累计确认,所以丢失的不需要重发。
计时器管理
-
重传计时器
-
持久计时器(persistence):用于零窗口互相等待时打破死锁。当得知零窗口时启动。
-
存活计时器(keep-alive):心跳包
-
等待计时器(time-wait):释放连接的主动方等待一段时间,等数据都超时再关闭连接。
重传时间(RTT)的设定
-
太长:低效
-
太短:重复发包
解决方法:
动态调整。new RTT = a(RTT) + (1-a)(new sample)
,a 是平衡因子。
重传超时(RTO)
RTTVAR = b(RTTVAR) + (1-b)|SRTT-Sample|
RTO = SRTT + 4*RTTVAR
Karn 算法:重传的包不用于估计,每次重传,RTO 加倍。
拥塞控制
隐式通知,TCP 发送方自己看着办。发送窗口受限于拥塞窗口大小。TCP 调整速率基于 AIMD 方法。
拥塞窗口(CWND):网络目前能消化的字节数。
发送窗口大小取 MIN(接收方WIN, CWnd)
发送方有效窗口:最大窗口-发送未确认=最大窗口-发送的+确认的
拥塞检测:通过丢包判断(超时未收到 ACK),没有拥塞就增加速率,有拥塞就降低速率。
ACK 时钟:反应低速链路的速率情况。发送方依据它,来避免连接低速路由时排队严重。平滑数据量。
拥塞控制算法
这篇文章不错。
慢启动(Slow-Start)法:初始 CWnd=1。每收到一个ACK,CWND«1。指数级增长速率。当连接建立时,拥塞窗口被初始化为一个报文段大小,每收到一个ACK,拥塞窗口就会增加一个报文段,发送方取拥塞窗口与通过窗口的最小值作为发送的上限。
拥塞窗口说白了就是阈值
【例子】 假设回环时间 10ms,无拥塞,接收窗口大小 24KB,分片大小 2KB,多久能满窗口发送?
【分析与解答】
初始 CWND=2KB,需要经过左移(平方) $\log_2 (12)≈3.58$ 次,向上取整 4 次,每次耗时 10ms,所以需要大概 40ms 达到最大窗口速率。
【例子】 假设拥塞窗口 18KB,最大分片大小 1KB。传着传着超时了,后来四个包都成功传输,此时窗口大小多大?
【分析与解答】 阈值 18KB,超时,阈值减半,变成 9KB,重新慢启动。1«4=16>9,因此经过四次成功传输,窗口大小变成了 9KB
在 TCP 的拥塞控制算法中,从慢启动开始,拥塞窗口按指数增长,即如果每一轮发送均收到 ACK,则拥塞窗口变为 2 倍;拥塞窗口增加到阈值时,增长速度减缓,改为线性增长(AI:每一轮发送成功后,拥塞窗口增加一个 MSS) 。当发生超时时,阈值=当前拥塞窗口值的一半,而拥塞窗口则降为 1 个 MSS,开始新的慢启动。
AIMD 法:收到 ACK,CWND+=1/CWND (缓慢增快速减).
一般有一个阈值,结合使用两种方法。达到阈值,进入拥塞避免(Congestion Avoidance)阶段,用 AIMD 法。直到拥塞开始。
阈值也是动态调整的,便于收敛。
TCP Tahoe:连续三个重复 ACK,或者超时之后,就从慢启动重来。
TCP Reno 快速恢复:连续收到三个重复 ACK,执行快速重传,然后进入快速恢复,阈值减少到二分之一窗口大小,CWND=Threshold。