TCP可靠数据传输
TCP可靠数据传输概述
TCP在IP层提供的不可靠服务的基础上实现可靠的数据传输服务
流水线机制
累积确定
触发重传的事件
- 超时
- 收到重复ACK
RTT和超时
如何设置定时器的超时时间,希望设置成大于RTT,但是RTT是动态的
如果设置的过短,会引起不必要的重传
如果设置的过长,则会对段丢失的反应慢
如何估计RTT?
SampleRTT:测量从段发出去到收到ACK的时间忽略重传
SampleRTT的变化:测量多个SampleRTT,求平均值,形成RTT的估计值EstimatedRTT
EstimatedRTT = (1-a) * EstimatedRTT + a * SampleRtt
加权指数平均,典型值: 0.125
定时器超时时间的设置:
- EstimatedRTT + “安全边界”
- EstimatedRTT变化大 -> 较大的边界
测量RTT的变化值: SampleRTT与EstimatedRTT的差值
DevRTT = (1 - B) * DevRTT + B * |SampleRTT - EstimatedRTT|
B典型值 : 0.25
TCP发送端程序
NextSeqNum = InitialSeqNum
SendBase = InitialSeqNum
loop (forever) {
switch(event):
event: data received from application above
create TCP segment with sequence number NextSeqNum
if (timer currently not running)
start timer
pass segment to IP
NextSeqNum = NextSeqNum + length(data)
event: timer timeout
retransmit not-yet-acknowledged segment with
smallest sequence number
start timer
event: ACK received, with ACK field value of y
if (y > SendBase) {
SendBase = y
if (there are currently not-yet-acknowledged segments)
start timer
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
快速重传机制
TCP 的实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大
-
重发丢失的分组之前要等待很长时间
通过重复ACK检测分组丢失 -
Sender会背靠背地发送多个分组
- 如果某个分组丢失,可能会引发多个重复的ACK
如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失
- 快速重传:在定时器超时之前即进行重传
快速重传算法
event: ACK received, with ACK field value of y
if (y > SendBase) {
SendBase = y
if (there are currently not-yet-acknowledged segments)
start timer
}
else {
increment count of dup ACKs received for y
if (count of dup ACKs received for y = 3) {
resend segment with sequence number y
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
TCP连接管理
TCP sender和receiver在传输数据前需要建立连接
初始化TCP变量
- Seq.#
- Buffer和流量控制信息
Client: 连接发起者
Server: 等待客户端请求 (具体可参见上面的java代码)
握手步骤:
1. Client发送syn 报文给Server(syn标识位置1)
- 给出初始seq
-
没有数据
- Server持有syn报文回送syn_ack报文(syn标识位置1)
-
Server分配缓冲区(syn泛洪攻击)
-
确定Server初始的seq
- 客户端收到syn_ack报文,返回ack报文.这次的ack可以带有初始数据(syn标识位置0)
四次挥手步骤
1. Client向Server发送FIN控制Segment
2. Server收到FIN,回复ACK,关闭连接,发送FIN
3. Client收到FIN,回复ACK
* 等待一段时间(怕Client发出去的ACK丢失)
4. Server收到ACK,连接关闭
步骤图:
SYN泛洪攻击
原理
攻击者发送大量的syn分组但是不对该分组进行响应,让Server端开启大量buffer浪费服务器端空间
防范
- 减少syn等待时间(不建议)
- syn缓存.
- 接收syn之后用hash表维护半开连接,等待下一次数据到来在开启真正的TCP缓存块.使用来源的一些信息(端口号)做hash,防止hashtable溢出
- 增大总连接缓冲区的大小
- 防火墙
TCP流量控制
接收方会为TCP连接分配buffer,如果发送方发的太快会导致接收方的buffer溢出,因此需要引入速度匹配机制
接收方会在Segment的头部字段将RcvWindow(接收窗口)的值告诉发送方,发送方限制自己已经发送但是还未收到ACK的数据不超过接收方的空闲RcvWindow尺寸
如果RcvWindow为0,会发生死锁.
所以其实发送方还是可以发送一个很小的段,以便捎回来一个新的RcvWindow.
拥塞控制原理
拥塞
非正式定义:”太多主机发送了太多数据或者发送速度太快,以至于网络无法处理”
表现为:
1. 分组丢失(路由器缓存溢出)
2. 分组延迟过大
拥塞的三个代价:
1. 拥塞时,分组的延时达到最大
2. 拥塞时,分组会导致路由器缓冲区溢出,导致丢失分组
3. 拥塞时,多跳网络中前几跳的努力会因为某一跳路由器的丢失分组而白费
当拥塞到一定程度时,整个网络将无法传输数据
端到端的拥塞控制方法:
1. 网络层不提供显式的支持
2. 端系统观察丢包和延迟等网络行为判断是否发生了拥塞
3. TCP采取这种方法
网络辅助的拥塞控制:
1. 路由器向发送方显式的反馈网络的拥塞信息
2. 简单的拥塞指示(1bit):SNA,DECbit,TCP/IP ECN,ATM
3. 指示发送方应该采取何种速率(定量)
ATM ABR网络中的拥塞控制
ARB:avaliable bit rate
* “弹性服务”
* 如果发送方路径”underloaded”就使用可用带宽
* 如果发送方路径拥塞就将发送速率降低到最低保障速率
RM(resource management)cells:专门用来指示网络拥塞状况的,穿插在正常的cell中发送
- 发送方发送
- 交换机设置RM cell位(网络辅助)
- NI bit: rate不许增长
- CI bit : 拥塞指示
- RM cell由接收方返回给发送方
总结起来就是发送方发出去,交换机和接收方置位,然后接收方统一返回给发送方
RMcell中还有显式的ER字段:两个字节(定量的指示)
- 拥塞的交换机可以将ER置为更低的值
- 发送方获知路径所能支持的最小速率
普通的RMcell中也有一个EFCI位指示拥塞,由交换机控制
如果RM cell前面的data cell的EFCI位被设为1,那么接收方在返回的RM cell中置CI位
TCP拥塞控制
TCP使用端到端的拥塞控制而不是使用网络辅助的拥塞控制,因为IP层不会向端系统提供显式的反馈.
设cwnd为拥塞窗口的大小,并假定发送方能通过cwnd调节发送速率
MSS为最大报文段大小
如果ack以非常慢的速度到达,则拥塞窗口将以非常慢的速度增加.另一个方面,如果确认以高速率到达,则该拥塞窗口将会更为迅速的增大.因为TCP使用确认来触发增大他的拥塞窗口的长度.
TCP的拥塞控制算法包含3个部分
加性增,乘性减:AIMD
- 慢启动
- 拥塞避免
- 快速恢复
慢启动
当一个TCP连接开始时,cwnd初始值为一个MSS的最小值,这时可用带宽远大于发送速率
所以,在慢启动阶段,每收到一个ACK,则拥塞窗口增加一个MSS.这样下去,每过一个RTT,拥塞窗口翻倍
什么时候结束这种指数增长呢?
* 如果检测到丢包事件,TCP将cwnd设置为1并重新开始慢启动,并且将一个变量threshold置为当前拥塞窗口的一半
* 如果当cwnd的值达到threshold时,将进入拥塞避免模式(不再翻翻,线性增加)
* 如果检测到三个ACK(并没有丢包那么严重,还能传一点东西),执行快重传并进入快恢复状态
拥塞避免
拥塞避免同样会增加cwnd,但是和慢启动不同,拥塞避免会每个RTT增加一个MSS(线性的)
如何结束拥塞避免呢?
- 超时时,和慢启动一样将cwnd设置为1并重新开始慢启动,并且将一个变量threshold置为当前拥塞窗口的一半
- 三个ACK时,将cwnd减半(为使测量结果更好,将threshold增加3个MSS).并且将threshold设为cwnd的一半.
快速恢复
对于引起进入快速恢复的每个冗余ACK,cwnd增加一个MSS.当最后一个ACK到达时,进入拥塞避免.如果出现超时事件,快速恢复在执行如同在慢启动和拥塞避免中相同的动作后,迁移到慢启动状态:当丢包事件发生后,cwnd被设置为一个MSS,并且threshold的值被设置为cwnd的一半.
拥塞控制总结
由于TCP Tahoe版本已经不再使用,这里只讨论Reno版本中的拥塞控制
- 初始状态为慢启动状态,threshold选定一个初始值(具体怎么选的依赖具体实现)
- 当cwnd小于threshold时,发送方慢启动状态,窗口指数增长
- 当cwnd大于threshold时,发送方拥塞避免状态,窗口线性增长
- 当发生3个ACK事件时先threshold = cwnd/2,然后cwnd = threshold,重新进入拥塞避免状态(还会加上3个ACK的)
- 当发生超时事件时,threshold = cwnd/2,cwnd = 1 ,然后进入慢启动状态