Network Layer无法保证
- 延迟
- 到达顺序
- 确认到达
- 准确内容
- 正确地址
CSE中的E2E层表示经典层次中的Transport Layer和Application Layer。这里主要讲的是TCP。
Transport Protocol
UDP(User Datagram Protocol)
适合传输简单应用的数据,不提供其他机制
TCP (Transmission Control Protocol)
适合不适合丢包的场景,提供重传、错误检测、保证顺序
RTP (Real-time Transport Protocol)
强调速度,适合流媒体(基于UDP,对丢包比较宽容)
一般我们使用TCP处理Network Layer可能发生的错误,解决的问题如下
- Assurance of at-least-once delivery
- Assurance of at-most-once delivery
- Assurance of data integrity
- Assurance of stream order & closing of connections
- Assurance of jitter control
- Assurance of authenticity and privacy
- Assurance of end-to-end performance
Assurance of At-least-once Delivery(重传)
RTT (Round-trip time,往返时延)
to_time process_time back_time (ack)
包中附带随机的nonce,ack时回传nonce,如果超时,则重传(同样的nonce)。那么,超时的阈值作为多少呢?
Fixed Timer
超时多少则是Trade-off,过长则丢包处理时间太久,过短则可能没有必要。如果写成固定的值则有风险,一旦对方无法提供服务,会造成大量的轮询。(查Wisconsin Time Server Meltdown)。
Adaptive Timer
为了处理这种情况,必须根据实际情况(RTT)进行调整,但是RTT是波动的,因此必须给出一定的余量作为Timeout。
Linux Kernel中使用这段代码进行迭代。(RTT期望不是真的数学期望,1/8只是个magic number)
- rtt_avg将当前一次的RTT和之前的RTT期望进行加权,算出目前的RTT期望。
- dev表示波动值
- rtt_dev将当前一次的RTT波动和之前的波动进行加权,算出目前的波动。
- Timeout将RTT期望增加一定余量
rtt_avg = a*rtt_sample (1-a)*rtt_avg; /* a = 1/8 */
dev = absolute(rtt_sample – rtt_avg);
rtt_dev = b*dev (1-b)*rtt_dev; /* b = 1/4 */
Timeout = rtt_avg 4*rtt_dev
NAK (Negative AcKnowledgment)
否定应答,由接受者检测包的丢失,回传给发送者,由发送方重发丢失的包,而不用Timer机制。
Assurance of At-most-once Delivery(处理重复重传)
1.维护nonce表:空间浪费 时间浪费
2.允许重复请求(要求幂等):时间浪费
这个问题没有完美的解法,因为接收方不知道发送方是否还会重传,这些nonce表必须保留,导致无止境增长。一种方法是超过一定时间后失效(但是会导致可能发生at-least-once错误),另一种是每次重启后清空表。
所以幂等性很重要!
Assurance of data integrity(校验码)
Checksum
Assurance of stream order & closing of connections(处理乱序)
Segment contains ID for where it fits
–E.g., "message 914, segment 3 of 7"
按序收包,乱序则存在buffer里,buffer满了则丢弃
滑动窗口
每个时刻只接受顺序在一定范围内的包,超范围则丢弃。如果最前的包收到了,那么窗口后移
Assurance of jitter control(延迟抖动)
方法:延迟所有到达的segment,作为缓冲。Dheadway是平均延迟,也就是说,池子中的segment,能支撑最大的抖动(Dlong并不是最大,但是超过99%)
Assurance of authenticity and privacy(加密)
使用公钥和私钥,对称密钥加密技术,公钥加密的只有使用私钥才能解读(由我READ),私钥加密的只有公钥才能解读(由我WRITE)
Assurance of end-to-end performance(握手)
并不等待所有包都传输完成,而是包成功传输后,窗口就进行滑动。注意,如果窗口开头的包传送失败,那么窗口不会向前滑动,而是等待这个包重传成功。
例如传送2-6,2失败,那么会等待2传送完后,直接跳到7-11,以保证其连续性
Fixed Window VS Sliding Window
window size ≥ RTT × bottleneck data rate以确保性能
TCP Congestion Control
由于堵塞时,重传次数会增加,性能会更加下降。因此window不能太大,否则重传会导致window卡住很久。
window size ≤ min(RTT x bottleneck data rate, Receiver buffer)以防止堵塞
TCP使用下面的算法迭代window size
AIMD (Additive Increase, Multiplicative Decrease)
每一次成功,window size (注意刚开始避免增速太慢使用*=2)
每一次丢包, window size / = 2
使用这种算法能够快速收敛到Fairness,也就是相同RTT两者的资源占用量尽可能公平
但是如果丢包频率高(信号不好时),尽管receiver没什么问题,window仍然会很小,导致性能受限,因此有很多新的协议。