3 传输层
3.4 TCP
3.4.1 TCP段结构
3.4.1.1 TCP段结构

3.4.1.2 序列号
序列号是segment中第一个字节的编号,而不是segment的编号(N e x t S e q N u m = S e q N u m + l e n g t h ( d a t a ) NextSeqNum = SeqNum + length(data)NextSeqNum=SeqNum+length(data))
建立TCP时,双方随机选择序列号
3.4.1.3 ACK
指的是希望接收到的下一个字节的序列号
使用的是累计确认机制(该序列号之前的所有字节均已被正确接收到)
关于乱序到达的Segment,TCP规范中没有规定,由TCP的实现者做出决策
3.4.2 TCP可靠数据传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务,使用了以下机制
流水线机制
累积确认
TCP使用单一重传定时器。触发重传的事件:超时;收到重复ACK
3.4.2.1 RTT和超时
为了设置定时器的超时时间,必须参考网络的RTT时间,而RTT是变化的,所以必须测量RTT
SampleRTT:测量从段发出去到收到ACK的时间。多次测量取平均值得到估计值EstimatedRTT(指数加权移动平均):
E s t i m a t e d R T T = ( 1 − α ) ∗ E s t i m a t e d R T T + α ∗ S a m p l e R T T EstimatedRTT = (1- \alpha)*EstimatedRTT + \alpha*SampleRTTEstimatedRTT=(1−α)∗EstimatedRTT+α∗SampleRTT (α \alphaα一般取0.125)
超时时间设置为:EstimatedRTT+ 安全边界。所以如果EstimatedRTT变化大就意味着需要设置较大的边界,所以就需要测量RTT的变化值:SampleRTT与EstimatedRTT的差值:
D e v R T T = ( 1 − β ) ∗ D e v R T T + β ∗ ∣ S a m p l e R T T − E s t i m a t e d R T T ∣ DevRTT = (1- \beta)*DevRTT +\beta *|SampleRTT-EstimatedRTT|DevRTT=(1−β)∗DevRTT+β∗∣SampleRTT−EstimatedRTT∣
所以超时时间的设置:T i m e o u t I n t e r v a l = E s t i m a t e d R T T + 4 ∗ D e v R T T TimeoutInterval = EstimatedRTT + 4*DevRTTTimeoutInterval=EstimatedRTT+4∗DevRTT
3.4.2.2 发送方
从应用层收到数据:创建Segment(设置序列号)–>开启计时器–>设置超时时间:
超时事件:重传引起超时的Segment,重启定时器
收到ACK:如果确认此前未确认的Segment,更新滑动窗口(SendBase),如果窗口中还有未被确认的分组,重新启动定时器。
3.4.2.3 接收方ACK生成
| 接收方事件 | 接收方TCP动作 |
|---|---|
| 收到按序到达的段(之前无等待发ACK的段) | 等待500ms,看是否有下一个段到达,如果没有就直接发送ACK |
| 收到按序到达的段(之前有等待发ACK的段) | 立即发送它的确认消息 |
| 收到乱序到达的段 | 立即发送重复的ACK消息,声明期望的段 |
3.4.2.4 快速重传机制
TCP的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大,所以重发丢失的分组之前要等待很长时间使之超时。
Sender会连续地发送多个分组,如果某个分组丢失,可能会引发多个重复的ACK,所以可以通过重复ACK检测分组丢失。如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失。
快速重传:在定时器超时之前即进行重传。
问题:为什么是收到3次相同的ACK?
3.4.3 TCP流量控制
接收方为TCP连接分配缓冲区(buffer),而上层应用可能处理buffer中数据的速度较慢,所以就需要流量控制以保证发送方不会传输的太多、太快以至于淹没接收方(buffer溢出)。
流量控制实际上是速度匹配机制。
假定TCP receiver丢弃乱序的段,则Buffer中的可用空间(spare room)= RcvWindow= RcvBuffer-[LastByteRcvd -LastByteRead]
Receiver通过在段的头部字段将RcvWindow 告诉Sender
Sender限制自己已经发送的但还未收到ACK的数据不超过接收方的RcvWindow尺寸
Receiver告知Sender RcvWindow=0,这会导致即使Reciver空闲了也无法通知Sender,所以需要一个机制来使Sender可以发送一个小的段从而可以带回Reciver的信息,避免了上面的死锁。
3.4.4 TCP连接管理
TCP sender和receiver在传输数据前需要建立连接
初始化TCP变量:如分配序列号、分配缓存区、交换流量控制信息。
3.4.4.1 TCP建立:三次握手
Client:连接发起者
Server: 等待客户连接请求
Client主机向Server发送一个TCP SYN segment:
SYN=1, seq=client_isn
- 不携带数据
- SYN标志位置1
- 传递选择的初始序列号
Server主机收到SYN,同意建立连接,回复SYNACK段
SYN=1, seq=serever_isn, ack=client_isn+1
- Server分配buffer
- 选择Server端的初始序列号,并告知Client
Client收到SYNACK,答复ACK段,SYN标志不再位置1,也可包含数据。
SYN=0, seq=client_isn+1, ack=server_isn+1
3.4.4.2 TCP关闭
Client和Server都可发起关闭请求,多数是客户机发起。
- Client向server发送TCP FIN 控制segment
- Server收到FIN, 回复ACK. 关闭连接, 发送FIN.
- Client收到FIN, 回复ACK。进入“等待” ——如果收到FIN,会重新发送ACK
- Server收到ACK. 连接关闭.
3.4.4.3 TCP生命周期
TCP客户端:

TCP服务端:

3.5 拥塞控制
拥塞的表现:
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
3.5.1 拥塞的成因和代价
λ i n \lambda_{in}λin:实际需要发送的数据
λ i n ′ \lambda'_{in}λin′:实际需要发送的数据+需要重传的数据
λ o u t \lambda_{out}λout:实际接收的数据
两个senders,两个receivers,一个路由器且无限缓存
这种条件下不需要重传,但拥塞时分组延迟太大
对于路由器:λ i n = λ o u t \lambda_{in} = \lambda_{out}λin=λout
两个senders,两个receivers,一个路由器且有限缓存
可能丢包,所以Sender需要重传分组
对于路由器:
- 情况a:Sender能够通过某种机制获知路由器buffer信息,有空闲才发。λ i n = λ i n ′ = λ o u t \lambda_{in}=\lambda'_{in}=\lambda_{out}λin=λin′=λout
- 情况b:丢失后才重发。λ i n ′ > λ o u t \lambda'_{in}>\lambda_{out}λin′>λout
- 情况c:分组丢失和定时器超时后都重发,λ i n ′ \lambda'_{in}λin′变得更大
由于重传,网络要做更多的工作,造成了资源的浪费。
四个发送方,多跳
可能丢包或超时都会引起重传。
当拥塞时,一个分组被drop,任何用于该分组的 “上游”传输能力全都被浪费掉
3.5.2 拥塞控制的方法
3.5.2.1 端到端拥塞控制
网络层不需要显式的提供支持,端系统通过观察loss,delay等网络行为判断是否发生拥塞。TCP采取这种方法。
3.5.2.2 网络辅助的拥塞控制
路由器向发送方显式地反馈网络拥塞信息,通过简单的拥塞指示(1bit:SNA, DECbit, TCP/IP ECN, ATM)指示发送方应该采取何种速率
3.5.2.3 ATM ABR拥塞控制
ABR(available bit rate):
如果发送方路径“underloaded”,使用可用带宽
如果发送方路径拥塞,将发送速率降到最低保障速率
RM(resource management) cells:
发送方发送
交换机设置RM cell位(网络辅助)
- NI bit: rate不许增长
- CI bit: 拥塞指示
RM cell由接收方返回给发送方
RM cell中显式的速率(ER)字段:两个字节。拥塞的交换机可以将ER置为更低的值,发送方获知路径所能支持的最小速率
数据cell中的EFCI位:拥塞的交换机将其设为1,如果RM cell前面的data cell的EFCI位被设为1,那么发送方在返回的RM cell中置CI位
3.5.3 TCP拥塞控制
Sender限制发送速率:L a s t B y t e S e n t − L a s t B y t e A c k e d < = C o n g W i n LastByteSent-LastByteAcked<= CongWinLastByteSent−LastByteAcked<=CongWin,则速率 r a t e ≈ C o n g W i n R T T B y t e s / s e c rate ≈\frac{CongWin}{RTT}\ Bytes/secrate≈RTTCongWin Bytes/sec
CongWin(发送窗口)保证了动态调整以改变发送速率,它反映所感知到的网络拥塞。
感知网络拥塞:Loss事件=timeout或3个重复ACK。发生loss事件后,发送方降低速率。
调整发送速率:加性增—乘性减;慢启动
3.5.3.1 加性增—乘性减: AIMD
原理:逐渐增加发送速率,谨慎探测可用带宽,直到发生loss,一旦发生loss,速率直接减半。
方法: AIMD
Additive Increase:每个RTT将CongWin增大一个MSS——拥塞避免
Multiplicative Decrease:发生loss后将CongWin减半
3.5.3.2 TCP慢启动: SS
原理:当连接开始时,指数性增长——收到每个ACK将CongWin加1 (即每个RTT将CongWin翻倍)。初始速率很慢,但是快速攀升。当CongWin达到Loss事件前值的1/2时,触发拥塞避免机制,指数性增长切换为线性增长。
实现方法:Threshold变量。Loss事件发生时,Threshold被设为Loss事件前CongWin值的1/2,然后开始线性增长。
Loss事件处理
3个重复ACKs:CongWin切到一半然后线性增长
Timeout事件:CongWin直接设为1个MSS,然后指数增长,达到threshold后, 再线性增长。
3个重复ACKs表示网络还能够传输一些 segments,而timeout事件表明拥塞更为严重。
3.5.4 TCP性能分析
TCP吞吐率
忽略掉Slow start,假定发生超时时CongWin的大小为W,吞吐率是W/RTT
超时后,CongWin=W/2,吞吐率是W/2RTT
平均吞吐率为:0.75W/RTT
TCP的公平性
公平:如果K个TCP Session共享相同的瓶颈带宽R,那么每个Session的平均速率为R/K。TCP是公平的。
公平性与UDP:多媒体应用通常不使用TCP,以免被拥塞控制机制限制速率。使用UDP的话可以以恒定速率发送,能够容忍丢失,于是产生了不公平。
公平性与并发TCP连接:某些应用会打开多个并发连接,如Web浏览器,于是产生公平性问题。
例子:链路速率为R,已有9个连接,新来的应用请求1个TCP,获得R/10的速率,新来的应用请求11个TCP,获得R/2的速率