TCP 概述
- 点对点 一个发送方一个接收方
- 可靠的、按序的字节流
- 流水线机制 TCP拥塞控制和流量控制机制设置窗口尺寸
- 发送方/接收方缓存
- 全双工
- 同一个连接中能够传输双向数据流
- 面向连接
- 通信双方在发送数据前必须建立连接
- 连接状态只在连接的两端中维护,在沿途节点中并不维护状态
- TCP 连接包括两台主机上的缓存、连接状态变量、socket 等
- 流量控制机制
序列号和 ACK
序列号
- 序列号指的是 segment 中第一个字节的编号,而不是 segment 的编号
- 建立 TCP 连接时,双方随机选择序列号
ACKs
- 希望接收到的下一个字节的序列号
- 累计确认:该序列号之前的所有字节均已被正确接收到
问题:接收方如何处理乱序到达的 segment?
TCP 规范中没有规定,由 TCP 的实现者做出决策。
TCP 可靠数据传输概述
- TCP 在 IP 层提高的不可靠服务基础上实现可靠数据传输服务
- 流水线机制
- 累计确认
- TCP 使用单一重传定时器 (和 SR 不同)
- 触发重传的事件
- 超时
- 收到重复 ACK
- 渐进式
- 暂不考虑重复 ACK
- 暂不考虑流量控制
- 暂不考虑拥塞控制
TCP RTT 和超时
如何设置定时器的超时时间
- 大于 RTT,但是 RTT 是变化的
- 过短,不必要的重传
- 过长,对段丢失时间反应慢
如何估计 RTT
SampleRTT
测量从段发出去到收到 ACK 的时间,忽略重传
SampleRTT 变化
测量多个 SampleRTT,求平均值,形成 RTT 的估计值 EstimatedRTT
指数加权移动平均典型值=0.125
EstimatedRTT=(1-x)*EstimatedRTT + x*EstimatedRTT
定时器超时时间的设置
- EstimatedRTT + “安全边界”
- EstimatedRTT 变化大 –> 较大的边界
测量 RTT 的变化值:SampleRTT 与 EstimatedRTT 的差值
DevRtt = (1-x)*DevRtt + x*|SampleRtt - EstimatedRTT|
一般 x = 0.25
定时器超时时间设置
TimeoutInterval = EstimatedRTT + 4*DevRTT
TCP 发送方事件
从应用层收到数据
- 创建 Segment
- 序列号是 Segment 第一个字节的编号
- 开启计时器
- 设置超时时间:TimeOutInterval
超时
- 重传引起超时的 Segment
- 重启定时器
收到 ACK
- 如果确认此前位确认的 Segment
- 更新 SendBase
- 如果窗口中还有未被确认的分组,重新启动定时器
TCP 重传示例
TCP 接收方
快速重传机制
- TCP 的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大,重发
丢失的分组之前要等待很长时间。 - 通过重复 ACK 检测分组丢失,Sender 会背靠背地发送多个分组,如果某个分组丢失,可能会引发多个重复 ACK。
- 如果 Sender 收到对同一个数据的 3 个 ACK,则假定该数据之后的段已经丢失。
快速重传解决这些问题,即在定时器超时之前即进行重传。
为什么是 3 次?
TCP 流量控制 速度匹配机制
接收方为 TCP 连接分配 buffer,上层应用可能处理 buffer 中数据的速度较慢。
flow control 发送方不会传输太多、太快以至于淹没接收方(buffer 溢出)
假定 TCP receiver 丢弃乱序的 segments。
buffer 中的可用空间(space room)= RcvWindow = RcvBuffer - (LastByteRcvd - LastByteRead)
- Receiver 通过在 segment 的头部字段将 RcvWindow 告诉 Sender
- Sender 限制自己已经发送的但还未收到 ACK 的数据不超过接收方的空闲 RcvWindow 尺寸
- Receiver 告诉 Sender RcvWindow=0,会出现什么情况?即使为0,发送方也会发送很小的段,以便收不到接收方的确认,从而导致死锁。
TCP 连接管理
TCP sender 和 receiver 在传输数据前需要建立连接,初始化 TCP 变量,Seq、Buffer 和 流量控制信息。
三次握手
- 客户端发送 TCP SYN 段 到服务器,指定 initial seq,不包含数据
- 服务器接收 SYN,返回 SYNACK 段,服务器分配 buffer,指定服务器端 initial seq
- 客户端接收 SYNACK,返回 ACK 段,此时可能会包含数据
客户端在收到服务器的确认后,可以不给服务器发送确认,达到攻击的目的。
四次挥手
- 客户机像服务器发送 TCP FIN 控制 Segment
- 服务器收到 FIN,回复 ACK,关闭连接,发送 FIN
- 客户机收到 FIN,回复 ACK,进入等待,如果收到 FIN,会重新发送 ACK,确认服务器成功释放资源
- 服务器收到 ACK,连接关闭
拥塞 congestion 控制
- 非正式定义:太多发送主机发送了太多数据或者发送速度太快,以至于网络无法处理
- 表现
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
- 拥塞控制(社会群体问题) VS 流量控制(个人的)
- A top 10 problem
拥塞的成因和代价
场景一
- 两个 senders,两个receivers
- 一个路由器,无限缓存
- 没有重传
- C 链路带宽
即在这种理想的情况下,当发送达到 C/2 时,拥塞分组延迟无限大,达到最大 throughput。
场景二
- 一个路由器,有限缓存
- sender 重传分组
- 情况a:Sender 能够通过某种机制获知路由器 buffer 信息,有空闲才发 lambda-in = lambda-out (goodput)
- 情况b:丢失后才重发 lambda’-in > lambda-out
- 情况c:丢失后和定时器超时后都重发,lambda’-in 变得更大
拥塞的代价:对给定的 goodput,要做更多的工作(重传),造成资源浪费。
场景三
- 四个发送方
- 多跳路由器
- 超时并重传
拥塞的另一个代价:当分组被 drop 时,任何用于该分组的上游传输能力全都被浪费掉。
拥塞控制原理
拥塞控制的方法
端到端拥塞控制
TCP 采用的方法
- 网络层不需要显式的提供支持
- 端系统通过观察 loss,delay 等网络行为判断是否发生拥塞
网络辅助的拥塞控制
- 路由器向发送方显式地反馈网络拥塞信息
- 简单的拥塞指示(1 bit)SNA,DEC bit、TCP/IPECN、ATM
- 指示发送方应该采取何种速率
案例:ATM ABR 拥塞控制
- ABR available bit rate
- 弹性服务
- 如果发送方路径 underloaded,使用可用带宽,如果发送方路径拥塞,将发送速率降到最低保障速率
- RM(resounce management)
- 发送方发送
- 交换机设置 RM cell 位(网络辅助)
- NI bit:发送速率不许增长
- CI bit:拥塞指示
- RM cell 由接收方返回给发送方
- 在 RM cell 中有显式的速率(ER)字段:两个字节
- 拥塞控制交换机可以将 ER 置为更低的值
- 发送方获知路径所能支持的最小速率
- 数据 cell 中的 EFCI 位:拥塞交换机将其设为1,如果 RM cell 前面的 data cell 的 EFCI 位被设为1,那么发送方在返回的 RM cell 中置 CI 位
TCP 拥塞控制的基本原理
发送方限制发送速率
lastByteSent - LastByteAcked <= CongWin
限制了已发送未确认的数据量
rate 约等于 CongWin/RTT Bytes/sec
CongWin 拥塞窗口
- 动态调整以改变发送速率
- 反映所感知到的网络拥塞
问题:如何感知网络拥塞
- Loss 事件:timeout 或 三个重复的 ACK
- 发生 loss 时间后,发送方降低速率
如何合理地调整发送速率
- 加性增-乘性减:AIMD
- 慢启动:SS slow start
加性增-乘性减 AIMD
- 原理:逐渐增加发送速率,谨慎探测可用带宽,直到发生 loss 事件
- 方法 AIMD
- Additive Increase: 每个 RTT 将 CongWin 增大一个 MSS(拥塞避免)
- Multiplicative Decrease: 发生 loss 后将 CongWin 减半
TCP 慢启动:SS
- TCP 连接建立时,CongWin = 1 个 mss
- 例:MSS=500 byte,RTT=200 ms,初始速率=20k bps
- 可用带宽可能远远高于初始速率,希望快速增长
- 原理:当连接开始时,指数性增长,每个 RTT 将 CongWin 翻倍,收到每个 ACK 进行操作
- 初始速率很慢,但是快速攀升
Threshold 变量
问题:何时应该指数性增长切换为线性增长(避免拥塞)?
答案是当 CongWin 达到 Loss 事件前值的 1/2 时
实现方法:
- 变量 Threshold
- Loss 事件发生时,Threshold 被设为 Loss 事件前 CongWin 值的 1/2
TCP series 1 Tahoe 版本发生 loss 时,拥塞窗口直接设置为1,Reno 版本改进了这种保守的做法。
面对不同loss事件的处理
- 三个重复 ACKs 快速恢复 fast recovery 窗口膨胀
- CongWin 切到一半
- 然后线性增长
- Timeout 事件
- CongWin 直接设为 1 个 MSS
- 然后指数增长
- 达到 threshold 后,再线性增长
为什么这样呢?
- 三个重复 ACKs 表示网络还能够传输一些 segments
- timeout 事件表明拥塞更为严重
总结
- When CongWin is below Threshold, sender in slow-start phase,window grows exponentially.
- When CongWin is above Threshold, sender is in congestion-avoidance phase, window grows linearly.
- When a triple duplicate ACK occurs, Threshold set to CongWin/2 and CongWin set to Threshold.
- When timeout occurs, Threshold set to CongWin/2 and CongWin is set to 1 MSS.
TCP 性能分析
TCP throughput 吞吐率
给定拥塞窗口大小和 RTT,TCP的平均吞吐率是多少?忽略慢启动。
- 假定发生超时时 CongWin 的大小为 W,吞吐率是 W/RTT
- 超时后,CongWin = W/2,吞吐率为 W/2RTT
- 平均吞吐率为 0.75W/RTT
未来的 TCP
对链路和路由器的要求很高,高到不现实。
TCP 的公平性
TCP 具有公平性。
如果 K 个 TCP Session 共享相同的瓶颈带宽 R,那么每个 Session 的平均速率为 R/k。
公平性与 UDP
- 多媒体应用通常不使用 TCP,以免被拥塞控制机制限制速率
- 使用UDP:以恒定速率发送,能够容忍丢失
- TCP 和 UDP 产生了不公平
- 研究:TCP friendly(对 TCP 友好的 UDP)
公平性与并发 TCP 连接
- 某些应用会打开多个并发连接
- web浏览器
- 产生公平性问题
为什么出现三次重复确认?