第二章
TCP协议
TCP/IP详解卷 1,CH17,CH18,CH19、
CH20,CH21,CH22,CH23,CH24
主要内容
? 2.1 TCP回顾
? 2.2 TCP连接的建立与终止
? 2.3 TCP的数据传输(交互数据流和成块数据流)
? 2.4 TCP的超时与重传
? 2.5 TCP的坚持定时器和保活定时器
? 2.6 TCP的未来和性能
2.1 TCP
? T C P提供一种面向连接的、可靠的字节流服务
? 在一个 T C P连接中仅有两方进行彼此通信
? 广播和多播不能用于 T C P
?
端口

发送 TCP报文段
TCP

TCP
接收缓存发送缓存
报文段 …报文段 报文段
端口
发送端 接收端
向发送缓存
写入数据块
从接收缓存
读取数据块
应用进程 应用进程 ?
TCP报文段被封装在一个 IP数据报中进行传输
T C P提供可靠性的方式
? 应用数据被分割成 T C P认为最适合发送的数据块
? 当 T C P发出一个段后,它启动一个定时器,等待目的端
确认收到这个报文段。如果不能及时收到一个确认,将重
发这个报文段。
? 当 T C P收到发自 T C P连接另一端的数据时,它将发送一
个确认。
? 当 TCP收到发自 TCP连接另一端的数据,它将发送一个确
认。
? TCP将保持它首部和数据的检验和
? 既然 TCP报文段作为 IP据报来传输,而 IPP数据报的到达
可能会失序,因此 TCP报文段的到达也可能会失序。如果
必要,TCP将对收到的数据进行重新排序,将收到的数
据以正确的顺序交给应用层。
? 既然 IP数据报会发生重复,TCP 的接收端必须丢弃重复
的数据。
? TCP还能提供流量控制
TCP的编号与确认
? 按字节编号
? 确认是对收到的数据的最高序号的确认,
表示期望下次收到的第一个字节的序号。
? 由于 TCP能够提供全双工通信,因此,
可以采用 捎带确认 以提高传输效率。
TCP的简单确认
发送窗口大小 = 1
发方 收方
Send 1 Receive 1
发方 收方
发送窗口大小 = 1
Send 1 Receive 1
Receive ACK 2 Send ACK 2
发方 收方
发送窗口大小 = 1
Send 1 Receive 1
Receive ACK 2 Send ACK 2
Send 2 Receive 2
发方 收方
发送窗口大小 = 1
Send 1 Receive 1
Receive ACK 2 Send ACK 2
Send 2 Receive 2
Receive ACK 3 Send ACK 3
发方 收方
发送窗口大小 = 1
Send 1 Receive 1
Receive ACK 2 Send ACK 2
Send 2 Receive 2
Receive ACK 3 Send ACK 3
Send 3 Receive 3
发方 收方
发送窗口大小 = 1
Send 1 Receive 1
Receive ACK 2 Send ACK 2
Send 2 Receive 2
Receive ACK 3 Send ACK 3
Send 3 Receive 3
Receive ACK 4 Send ACK 4
发方 收方
发送窗口大小 = 1
TCP 的编号与确认号
Source
Port
Dest.
Port
…Sequence
#
Acknowledgement
#
Source Dest,Seq,Ack.
1028 23 10 1
I just
sent #10.
I just got #10,
now I need #11.
Source
Port
Dest.
Port …
Sequence
#
Acknowledgement
#
1028 23
Source Dest.
10
Seq.
1
Ack.
102823
Source Dest.
11
Seq.
1
Ack.
I just
sent #10.
Source
Port
Dest.
Port …
Sequence
#
Acknowledgement
#
1028 23
Source Dest.
11
Seq.
2
Ack.
1028 23
Source Dest.
10
Seq.
1
Ack.
102823
Source Dest.
11
Seq.
1
Ack.
I just got #10,
now I need #11.
I just
sent #11.
Source
Port
Dest.
Port …
Sequence
#
Acknowledgement
#
1028 23
Source Dest.
11
Seq.
101
Ack.
1028 23
Source Dest.
10
Seq.
100
Ack.
102823
Source Dest.
11
Seq.
100
Ack.
102823
Source Dest.
12
Seq.
101
Ack.
I just got #11,
now I need #12.
I just
sent #11.
TCP 的包格式
源端口 (16) 目的端口 (16)
顺序号 (32)
头长 (4)
确认序号 (32)
保留 (6) 窗口 (16)
检验和 (16) 紧急指针 (16)
选项和填充 (可选 )
数据 (可变长 )
20
字节
位 0 15 16 31
UR
G
AC
K
PS
H
RS
T
SY
S
FI
N
TCP
首部
20 字节的
固定首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FIN
32 bit
SY
N
RS
T
PS
H
AC
K
UR
G
比特 0 8 16 24 31
填 充
TCP 数据部分TCP 首部TCP 报文段
IP 数据部分IP 首部
发送在前
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
源端口和目的端口字段 —— 各占 2 字节。端口是运输
层与应用层的服务接口。运输层的复用和分用功能都
要通过端口才能实现。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
序号字段 —— 占 4 字节。 TCP 连接中传送的数据流
中的每一个字节都编上一个序号。序号字段的值则指
的是本报文段所发送的数据的 第一个字节的序号 。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
确认号字段 —— 占 4 字节,是 期望收到对方的下一个
报文段的数据的第一个字节的序号 。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
首部长度 —— 占 4 bit,它指出 TCP 报文段首部有多少
个 4 字节
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
保留字段 —— 占 6 bit,保留为今后使用,但目前
应置为 0。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
紧急比特 URG —— 当 URG ? 1 时,表明紧急指
针字段有效。它告诉系统此报文段中有紧急数据,
应尽快传送 (相当于高优先级的数据 )。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
确认比特 ACK —— 只有当 ACK ? 1 时确认号字
段才有效。当 ACK ? 0 时,确认号无效。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
推送比特 PSH (PuSH) —— 接收 TCP 收到推送比特
置 1 的报文段,就尽快地交付给接收应用进程,而不
再等到整个缓存都填满了后再向上交付。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
复位比特 RST (ReSeT) —— 当 RST ? 1 时,表明 TCP
连接中出现严重差错(如由于主机崩溃或其他原因),
必须释放连接,然后再重新建立运输连接。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
同步比特 SYN —— 同步比特 SYN 置为 1,就表示
这是一个连接请求或连接接受报文。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
终止比特 FIN (FINal) —— 用来释放一个连接。当
FIN ? 1 时,表明此报文段的发送端的数据已发送完
毕,并要求释放运输连接。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
窗口字段 —— 占 2 字节,用来控制对方发送的数据量,单位为字节。 TCP 连
接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以
确定对方的发送窗口的上限,也称为通知窗口。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
检验和 —— 占 2 字节 。 检验和字段 检验的范围包括首部
和数据 这两部分 。 在计算检验和时, 要在 TCP 报文段的前
面加上 12 字节的伪首部 。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
紧急指针字段 —— 占 16 bit。 紧急指针指出在本报文段
中的紧急数据的最后一个字节的序号 。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
选项字段 —— 长度可变 。 TCP 只规定了一种选项, 即 最大
报文段长度 MSS (Maximum Segment Size)。 MSS 告诉对方
TCP:, 我的缓存所能接收的报文段的数据字段的最大长度
是 MSS 个字节 。,
MSS 是 TCP 报文段中的 数据字段 的最大长度。
数据字段加上 TCP 首部
才等于整个的 TCP 报文段。
TCP
首部
20
字节
固定
首部
目 的 端 口
首部
长度
检 验 和
选 项 (长 度 可 变)
源 端 口
序 号
紧 急 指 针
窗 口
确 认 号
保 留 FINSYNRSTPSHACKURG
比特 0 8 16 24 31
填 充
填充字段 —— 这是为了使整个首部长度是 4 字节的
整数倍 。
2.2 TCP连接的建立与终止
? 三次握手建立连接
? 提供全双工的可靠交付的服务
? 按字节编号
? 采用可变窗口进行流量控制
一、建立连接
? 在连接建立过程中要解决三个问题:
? 要使每一方能够确知对方的存在
? 要允许双方协商一些参数,如,MTU,Wmax、
QoS等
? 能对运输实体的资源进行分配,如:缓存大小、
连接表中的项目等。
? 采用 Client/Server方式工作
Send SYN
(seq=100 ctl=SYN)
SYN received
Host A Host B
TCP 使用三次握手建立连接
1
Send SYN
(seq=100 ctl=SYN)
SYN received
Send SYN,ACK
(seq=300 ack=101 ctl=syn,ack)
Host A Host B
SYN received
1
2
Send SYN
(seq=100 ctl=SYN)
SYN received
Send SYN,ACK
(seq=300 ack=101 ctl=syn,ack)
Established
(seq=101 ack=301 ctl=ack)
Host A Host B
1
2
3
SYN received
二,释放连接
Send FIN
(FIN,seq=X)
Host A Host B
1
FIN received
Send ACK
(ACK=X+1)
Host A Host B
ACK received
1
2
Send FIN
(FIN,seq=X)
Half-close 半关闭
Host A Host B
1Send FIN
(FIN,seq=X)
FIN received
Send ACK
(ACK=X+1)
Host A Host B
ACK received
1
2
Send FIN
(FIN,seq=X)
Half-close 全关闭
FIN received
Host A Host B
1 Send FIN (FIN,seq=X)
FIN received
Send ACK,FIN
(FIN,seq=y,ACK=X+1)
Host A Host B
FIN,ACK received
1
2
Send FIN
(FIN,seq=X)
FIN received
Send ACK,FIN
(FIN,seq=y,ACK=X+1)
Host A Host B
FIN,ACK received
1
2
Send FIN
(FIN,seq=X)
3 Send ACK,FIN
(FIN,ACK=Y+1)
Full-close 全关闭
连接建立与终止的时间系列
初始序列号 ISN
? 当一端为建立连接而发送它的 SYS时,它为连接
选择一个初始序号。 ISN随时间而变化,因此每
个连接都将具有不同的 ISN。
? 在 4, 4 B S D(和多数的伯克利的实现版)中,
系统初始化时初始的发送序号被初始化为 1,这
个变量每 8 ms加 1,另外,每次建立一个连接后,
这个变量将增加 64000。
连接终止期间报文段的正常交换
三,连接建立的超时
有很多情况导致无法建立连接。如:
? 服务器主机没有处于正常状态。
? 服务器忙
B S D版的 T C P软件采用一种 500 ms的定
时器
? 当我们键入一个命令(如 t e l n e t)后,将建立一个 6秒
的定时器( 1 2个时钟滴答( t i c k)),但它可能在之
后的 5, 5秒 ~ 6秒内的任意时刻超时。
? 尽管定时器初始化为 1 2个时钟滴答,但定时计数器会在
设置后的第一个 0~500 ms中的任意时刻减 1。从那以后,
定时计数器大约每隔 500 ms减 1,但在第 1个 500 ms内
是可变的(我们使用限定词, 大约, 是因为在 T C P每隔
500 ms获得系统控制的瞬间,系统内核可能会优先处理
其他中断)。
TCP的 500 ms定时器
当滴答计数器为 0时,6秒的定时器便会超时,这个定时器会
在以后的 2 4秒( 4 8个滴答)重新复位。之后的下一个定时器
将更接近 2 4秒,因为当 T C P的 500 ms定时器被内核调用时,
它就会被修改一次。
四、最大报文段长度 MSS
? MSS表 示 TCP报文段的数据长度
? 当一个连接建立时,连接的双方都要通告各自的
MSS。
? 当建立一个连接时,每一方都有用于通告它期望
接收的 M S S选项( M S S选项只能出现在 S Y N
报文段中)。
? 如果一方不接收来自另一方的 M S S值,则 M S S
就定为默认值 5 3 6字节,
MSS的大小
? 如果没有分段发生,MSS越大越好。
? 当 T C P发送一个 S Y N时,或者是因为一个本地
应用进程想发起一个连接,或者是因为收到了另
一端主机的一个连接请求,它能将 M S S值设置
为外出接口上的 M T U长度减去固定的 I P首部和
T C P首部长度。
? 如果目的 I P地址为, 非本地的,M S S通常的默
认值为 5 3 6。
五、复位报文段
? 一般说来,无论何时一个报文段发往基准
的连接出现错误,T C P都会发出一个复位
报文段。如:
? 到不存在的端口的连接请求
? 异常终止一个连接
? 检测半打开连接
到不存在的端口的连接请求
? 产生复位的一种常见情况是当连接请求到
达时,目的端口没有进程正在听。
? 对于 U D P,当一个数据报到达目的端口时,
该端口没在使用,它将产生一个 I C M P端
口不可达的信息。
? 而 T C P则使用复位
异常终止一个连接
? 在排队数据都已发送之后才发送 F I N,正常情况下没有任
何数据丢失。但也有可能发送一个复位报文段而不是 F I N
来中途释放一个连接,称这为异常释放。异常终止一个连
接对应用程序来说有两个优点:
? ( 1)丢弃任何待发数据并立即发送复位报文段;
? ( 2) R S T的接收方会区分另一端执行的是异常关闭还是
正常关闭。
? 应用程序使用的 A P I必须提供产生异常关闭而不是正常关
闭的手段。
检测半打开连接
? 如果一方已经关闭或异常终止连接而另一方却还不知道,
我们将这样的 T C P连接称为半打开的。任何一端的主机
异常都可能导致发生这种情况。只要不打算在半打开连接
上传输数据,仍处于连接状态的一方就不会检测另一方已
经出现异常。
? 如果服务器突然断电又重新启动其 T C P,它将丢失复位
前连接的所有信息,因此它不知道数据报文段中提到的连
接。
? T C P的处理原则是接收方以复位作为应答
六、同时打开
七、同时关闭
八,TCP选项 RFC793 RFC1323
T
C
P






CLOSED
ESTABLISHED
LISTEN
CLOSE_WAIT
FIN_WAIT_1
SYN_RCVD
FIN_WAIT_2
CLOSING
TIME_WAIT
SYN_SENT
LAST_ACK
主动打开
被动打开
被动关闭
主动关闭
起点
被动打开 主动打开
发送 SYN
同时打开
收到 SYN,发送 SYN,ACK
收到 ACK
数据传送
阶段
关闭
发送 FIN
关闭
发送 FIN
关闭
发送 FIN
收到 RST
收到 SYN
发送 SYN,ACK
关闭
或超时
收到 ACK
收到 SYN,ACK
发送 ACK
收到 ACK收到 ACK
收到 FIN
发送 ACK
收到 FIN,ACK
发送 ACK
收到 FIN
发送 ACK
同时关闭
收到 FIN
发送 ACK
发送 SYN
定时经过两倍报文段寿命后
关闭
TCP正常连接建立和终止所对应的状态
2.3 TCP的数据传输
? 包括 交互数据流 和 成块数据流
? 若按分组数量计算,约有一半的 T C P报文段包含成块数据
(如 F T P、电子邮件和 U s e n e t新闻),另一半则包含
交互数据(如 Te l n e t和 R l o g i n)。
? 若按字节计算,则成块数据与交互数据的比例约为 9,1 。
? T C P需要同时处理这两类数据,但使用的处理算法则有所
不同。
一,TCP的交互数据流
? 输入 Rlogin 或 Telnet后会产生 4个报文段:
? ( 1)来自客户的交互按键;
? ( 2)来自服务器的按键确认;
? ( 3)来自服务器的按键回显;
? ( 4)来自客户的按键回显确认。
一般可以将报文段 2和 3进行合并 —按键确认与按键回显
一起发送(捎带确认)。
Telnet有一个选项允许客户发送一行到服务器,通过使
用这个选项可以减少网络的负载。
? 在象 R l o g i n这样的连接上客户一般每次发送
一个字节到服务器,这就产生了一些 4 1字节长的
分组,2 0字节的 I P首部,2 0字节的 T C P首部
和 1个字节的数据。
? 在局域网上,这些小分组(被称为微小分组)通
常不会引起麻烦,因为局域网一般不会出现拥塞。
? 但在广域网上,这些小分组则会增加拥塞出现的
可能。
? 一种简单和好的方法就是采用 N a g l e算法
RFC 896
Nagle算法
? 若数据是逐个字节到达发送端,则发送端就将第一个
字节发送出去,并将后面到达的字节缓存起来。
? 当收到对第一个字节的确认后,再将缓存中的所有字
符组装成一个报文发送出去,同时继续对到达的字符
进行缓存。
? 只有在收到确认后才发送下一个报文。
? 为解决字符到达快、网络速度慢的情况,还规定:当
到达的字节达到窗口大小的一半或者已达到报文的最
大长度时,就立即发送下一个报文。
? 虽然 Nagle算法已被很多 TCP程序采用,但是
有时候最好不用。
? 如:在 Internet上使用 X-Windows,小消息
(鼠标移动)必须无时延地发送,以便为进行
某种操作的交互用户提供实时的反馈。
? 当服务器接收到该字符后,它并不发送确认,
而是继续等待接收序列中的其他字符。
? 对交互用户而言,这将产生明显的时延,使用
户无法忍受,这时最好关闭这个算法。
糊涂窗口综合症
? 接受端的缓存已满,而交互式的应用进程一次只从缓存
中读取 1个字符,然后向发送端发确认,并通知窗口为 1
字节(发 40字节的 IP报文)。
? 接着,发送端又发来 1个字节(发 41字节的 IP报文)。
? 接收端发确认,仍然通知窗口为 1字节。如此进行下
去 …
? 使得网络效率非常低
两种解决方法
? Clark方法:禁止接收方发送 1字节的窗口,而是让接收
端等待一段时间,等到缓存能容纳一个最长的报文段,或
者空出一般的空间,才发送确认。
? 发送端不要发送太小的报文段,而是将数据积累成足够大
的报文段,或者当接收端有一半的空闲缓存时才发送。
? 这两种方法可配合使用
? 交互数据总是以小于最大报文段长度的分
组发送
二,TCP的成块数据流
? TCP 采用大小可变的滑动窗口进行流量控制 。 窗口大小
的单位是 字节 。
? 在 TCP 报文段首部的窗口字段写入的数值就是当前给对
方设置的发送窗口数值的上限 。
? 发送窗口在连接建立时由双方商定 。 但在通信的过程中,
接收端可根据自己的资源情况, 随时动态地调整对方的发
送窗口上限值 (可增大或减小 )。
TCP 的可变滑动窗口
发方 收方
Window size = 3
Send 2
Window size = 3
Send 1
Window size = 3
Send 3
发方 收方
Window size = 3
Send 2
Window size = 3
Send 1
Window size = 3
Send 3 ACK 3
Window size = 2
Packet 3 is
Dropped
发方 收方
Window size = 3
Send 2
Window size = 3
Send 1
Window size = 3
Send 3 ACK 3
Window size = 2
Packet 3 is
Dropped
Window size = 2
Send 4
Window size = 2
Send 3
发方 收方
Window size = 3
Send 2
Window size = 3
Send 1
Window size = 3
Send 3
ACK 3
Window size = 2
Packet 3 is
Dropped
Window size = 2
Send 4
Window size = 2
Send 3
ACK 5
Window size = 2
Window size = 3发方 收方
收到确认即可前移
100 200 300 400 500 600 700 800 900101 201 301 401 501 601 701 8011
发送窗口
可发送 不可发送
指针
? 发送端要发送 900 字节长的数据,划分为 9 个
100 字节长的报文段,而发送窗口确定为 500
字节。
? 发送端只要收到了对方的确认,发送窗口就可前
移。
? 发送 TCP 要维护一个指针。每发送一个报文段,
指针就向前移动一个报文段的距离。
收到确认即可前移
100 200 300 400 500 600 700 800 900101 201 301 401 501 601 701 8011
可发送 不可发送
指针
100 200 300 400 500 600 700 800 900101 201 301 401 501 601 701 8011
发送窗口
可发送 不可发送
指针 发送窗口前移
? 发送端已发送了 400 字节的数据,但只收到对前 200 字节
数据的确认,同时窗口大小不变。
? 现在发送端还可发送 300 字节。
已发送
并被确认
已发送但
未被确认
100 200 300 400 500 600 700 800 900101 201 301 401 501 601 701 8011
已发送
并被确认
已发送但
未被确认 可发送 不可发送
指针
100 200 300 400 500 600 700 800 900101 201 301 401 501 601 701 8011
已发送
并被确认 可发送
不可
发送
指针
发送窗口前移
发送窗口缩小
? 发送端收到了对方对前 400 字节数据的确认,但
对方通知发送端必须把窗口减小到 400 字节。
? 现在发送端最多还可发送 400 字节的数据。
利用可变窗口大小进行流量控制
双方确定的窗口值是 400
SEQ = 1
SEQ = 201
SEQ = 401
SEQ = 301
SEQ = 101
SEQ = 501
ACK = 201,WIN = 300
ACK = 601,WIN = 0
ACK = 501,WIN = 200
主机 A 主机 B
允许 A 再发送 300 字节(序号 201 至 500)
A 还能发送 200 字节
A 还能发送 200 字节(序号 301 至 500)
A 还能发送 300 字节
A 还能发送 100 字节(序号 401 至 500)
A 超时重发,但不能发送序号 500 以后的数据
允许 A 再发送 200 字节(序号 501 至 700)
A 还能发送 100 字节(序号 501 至 700)
不允许 A 再发送(到序号 600 的数据都已收到)
SEQ = 201 丢失!
发送数据时,既要考虑到接收端能力,又要使
网络不发生拥塞,发送窗口应满足:
?通知窗口
接收端根据接收能力许诺的窗口值
?拥塞窗口
发送端根据网络拥塞情况得出的窗口值,是指发送方一
次可传送的字节数。
?发送窗口
=Min[通知窗口,拥塞窗口 ]
使用的拥塞控制技术
? 慢开始(慢启动)
? 加速递减(乘法减小)
? 拥塞避免
1,当一个连接初始化时,拥塞窗口置为 1个 MSS,并设置慢启动的门
限窗口值。
2.发送端若收到了对所有发出的报文段的确认,就在下一次发送时将
拥塞窗口加倍;若出现超时,则将当时的拥塞窗口值减半,作为
新的门限窗口值,同时将拥塞窗口置为 1个 MSS。
3,拥塞窗口重新从 1个 MSS开始按指数规律增长,但增长到新的门限
窗口值时,就每次只将拥塞窗口加 1个 MSS,使拥塞窗口按线性
规律增长。当网络又出现超时时,仍重复上述过程。
实现步骤
?,慢启动, 是指每出现一次超时,拥塞窗口都降低到 l,
使报文段慢慢注人到网络中。
?, 加速递减, 是指每出现一次超时,就将门限窗口值
减半。若超时频繁出现,则门限窗口减小的速率是很
快的。
?, 拥塞避免, 是指当拥塞窗口增大到门限窗口值时,
就将拥塞窗口指数增长速度降低为线性增长,避免网
络再次出现拥塞。
慢开始和拥塞避免算法的实现举例
当 TCP 连接进行初始化时,将拥塞窗口置为 1。图中
的窗口单位不使用字节而使用 报文段 。
慢开始门限的初始值设置为 16 个报文段,
即 ssthresh = 16。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
发送端的发送窗口不能超过拥塞窗口 cwnd 和接收端
窗口 rwnd 中的最小值。我们假定接收端窗口足够大,
因此现在发送窗口的数值等于拥塞窗口的数值。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
在执行慢开始算法时,拥塞窗口 cwnd 的初始值为 1,
发送第一个报文段 M0。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
发送端收到 ACK1 (确认 M0,期望收到 M1)后,将
cwnd 从 1 增大到 2,于是发送端可以接着发送 M1 和
M2 两个报文段。
慢开始和拥塞避免算法的实现举例
接收端发回 ACK2 和 ACK3。发送端每收到一个对新报
文段的确认 ACK,就把发送端的拥塞窗口加 1。现在
发送端的 cwnd 从 2 增大到 4,并可发送 M4 ~ M6共 4
个报文段。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
发送端每收到一个对新报文段的确认 ACK,就把发送
端的拥塞窗口加 1,因此拥塞窗口 cwnd 随着传输次数
按指数规律增长。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
当拥塞窗口 cwnd 增长到慢开始门限值 ssthresh 时
(即当 cwnd = 16 时),就改为执行拥塞避免算法,
拥塞窗口按线性规律增长。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
ssthresh = 16
慢开始 慢开始
线性规律增长
拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
假定拥塞窗口的数值增长到 24 时,网络出现超时(表
明网络拥塞了)。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
更新后的 ssthresh 值变为 12(即发送窗口数值 24 的
一半),拥塞窗口再重新设置为 1,并执行慢开始算
法。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
慢开始和拥塞避免算法的实现举例
当 cwnd = 12 时改为执行拥塞避免算法,拥塞窗口
按按线性规律增长,每经过一个往返时延就增加一
个 MSS 的大小。
2 4 6 8 10 12 14 16 18 20 220
0
4
8
12
16
20
24
传输次数
拥塞窗口 cwnd
进入拥塞避免
发生超时
指数规律增长
线性规律增长
ssthresh = 16
慢开始 慢开始拥塞避免 拥塞避免
更新后的 ssthresh = 12
进入拥塞避免
乘法减小
(multiplicative decrease)
?,乘法减小, 是指不论在慢开始阶段还是拥塞避
免阶段, 只要出现一次超时 ( 即出现一次网络拥
塞 ), 就把慢开始门限值 ssthresh 设置为当前
的拥塞窗口值乘以 0.5。
? 当网络频繁出现拥塞时, ssthresh 值就下降得
很快, 以大大减少注入到网络中的分组数 。
加法增大
(additive increase)
?,加法增大, 是指执行拥塞避免算法后, 当收到
对所有报文段的确认就将拥塞窗口 cwnd增加一
个 MSS 大小, 使拥塞窗口缓慢增大, 以防止网
络过早出现拥塞 。
使用这些技术的 —个前提
? 由于通信线路带来的误码而使得分组丢失的概
率很小(远小于 1%)。因此,只要出现分组
丢失或迟延过长而引起超时重发,就意味着在
网络中的某个地方比现了拥塞。下面结合上图
来讨论拥塞控制的实现步骤:
? 拥塞窗口是指发送方一次可传送的字节数 。
必须强调指出
?,拥塞避免, 并非指完全能够避免了拥塞 。 利
用以上的措施要完全避免网络拥塞还是不可能
的 。
?, 拥塞避免, 是说在拥塞避免阶段把拥塞窗口
控制为按线性规律增长, 使网络比较不容易出
现拥塞 。
8.4 TCP的超时与重传
? T C P提供可靠的运输层
? 它使用的方法之一就是确认从另一端收到的数据
? 但数据和确认都有可能会丢失
? T C P通过在发送时设置一个定时器来解决这种问

? 如果当定时器溢出时还没有收到确认,它就重传
该数据。
? 关键就在于超时和重传的策略,即怎样决定 超时
间隔 和如何确定 重传的频率 。
对每个连接,T C P管理 4个不同的定时器
? 重传定时器 发出数据后启用
? 坚持定时器 使窗口大小信息保持不断流动,即
使另一端关闭了其接收窗口。
? 保活定时器 可检测到一个空闲连接的另一端何
时崩溃或重启。
? 2MSL定时器 测量一个连接处于 TIME_WAIT状
态的时间。
TCP的重传机制
? 重传机制是 TCP 中最重要和最复杂的问题之一
? TCP每发送一个报文段,就设置一次计时器 T’,超时
未收到确认就重传。
? T’太小,使得大量报文段重传,给网络增加许多不应
有的负担; T’太大,使网络的传输效率降低。
? 传输层的重传定时器(超时计时器)的重传时间 T’究
竟应设置多大?
重传定时器
? 最好稍大于往返时延
? 关键:测量往返时延
往返时延的方差很大
? 由于 TCP 的下层是一个互连网环境,IP 数据报所选择的
路由变化很大。因而运输层的往返时延的方差也很大。
时间
数据链路层
运输层
T1 T2 T3
往返时延的
概率分布
? 记录每一个报文段发出的时间
? 再记录收到相应的确认报文段的时间
? 这两个时间之差就是报文段的往返时延
? 将各个报文段的往返时延样本加权平均,
就得出报文段的平均往返时延 RTT。
自适应算法
? 每测量到一个新的往返时延样本,就按
下式重新计算一次平均往返时延 RTT
平均往返时延
RTT ? ? ? RTT旧 ? (1 ? ?) ? RTT新
0 ? ? ? 1。
参数 ? 的选择
? 若 ? 很接近于 1,表示新算出的平均往返时延
RTT 和原来的值相比变化不大,而新的往返时
延样本的影响不大 (RTT 值更新较慢 )。
? 若选择 ? 接近于零,则表示加权计算的平均往
返时延 RTT 受新的往返时延样本的影响较大
(RTT 值更新较快 )。
? 典型的 ? 值为 7/8。
超时重传时间 RTO
(RetransmissionTime-Out)
? 计时器的 RTO 应略大于上面得出的 RTT,即:
RTO ? ? ? RTT ? 大于 1
? 若取 ? 很接近于 1,发送端可及时地重传丢失的
报文段,因此效率得到提高。
? 但若报文段并未丢失而仅仅是增加了一点时延,
那么过早地重传反而会加重网络的负担。
? 因此 TCP 原先的标准推荐将 ? 值取为 2。
往返时延 RTT?
往返时间的测量相当复杂
? TCP 报文段 1 没有收到确认。
? 重传后收到了确认报文段 ACK。
? 如何判定此确认报文段是对原来的报文段的确认,还是对
重传的报文段的确认?
发送一个
TCP 报文段
超时重传
TCP 报文段 收到 ACK
时间1 2
往返时延 RTT?
是对哪一个报文段
的确认?
? 若收到的确认是对重传报文的确认,却被源
站当成是对原来报文的确认,那么,这样计
算出的往返时延就会偏大
? 若收到的确认是对原来报文的确认,却被源
站当成是对重传报文的确认,那么,这样计
算出的往返时延就会偏小。
Karn算法
? 在计算平均往返时延时,只要报文段重
传了,就不采用其往返时延样本。
? 引起重传时间无法更新
修正的 Karn 算法
? 报文段每重传一次, 就将重传时间增大一些
RTO 新 ?? ? RTO 旧
? 系数 ? 的典型值是 2
? 当不再发生报文段的重传时,才根据报文段的往返
时延更新平均往返时延 RTT 和重传时间的数值。
? 实践证明,这种策略较为合理。
2.5 TCP的坚持定时器和保活定时器
? TCP的坚持定时器
? TCP的保活定时器
一,TCP的坚持定时器
? 如果一个确认丢失了,则双方就有可能因为等待
对方而使连接终止:接收方等待接收数据(因为
它已经向发送方通告了一个非 0的窗口),而发
送方在等待允许它继续发送数据的窗口更新。
? 为防止这种死锁情况的发生,发送方使用一个坚
持定时器 (persist timer)来周期性地向接收方查
询,以便发现窗口是否已增大。
二,TCP的保活定时器
? 可以没有任何数据流通过一个空闲的 T C P连接
? 也就是说,建立 TCP连接后,T C P连接的双方可以都不
向对方发送数据。
? 一旦通信双方建立起 TCP连接,如果不释放连接,两端的
主机也没有被重启,则连接依然保持建立。
? 许多时候一个服务器希望知道客户主机是否崩溃并关机或
者崩溃又重新启动。
? 许多实现提供的保活定时器可以提供这种能力。
保活并不是 TCP规范中的一部分。
有 3个不使用保活定时器的理由:
? (1) 在出现短暂差错的情况下,这可能会使一个
非常好的连接释放掉。
? ( 2)它们耗费不必要的带宽
? ( 3)在按分组计费的情况下会在互联网上花掉
更多的钱
? 然而,许多实现提供了保活定时器。
保活定时器是一个有争论的功能
? 许多人认为如果需要,这个功能不应该在 TCP中
提供,而应该由应用程序来完成。
? 保活功能主要是为服务器应用程序提供的。服务
器应用程序希望知道客户主机是否崩溃,从而可
以知道客户是否使用该资源。
? 许多版本的 R l o g i n和 Te l n e t服务器默认使
用这个选项。
2.6 TCP的未来和性能
? 路径 MTU发现机制
? 长肥管道(具有很大的带宽时延乘积的 网络 )
以及 T C P在这些网络上所具有的局限性
TCP的路径 MTU发现
? 在连接建立时,T C P使用输出接口或对端
声明的 M S S中的最小 M T U作为起始的报
文段大小。路径 M T U发现不允许 T C P超
过对端声明的 M S S。如果对端没有指定一
个 M S S,则默认为 5 3 6。
? 一旦选定了起始的报文段大小,在该连接上的所有被 T C
P发送的 I P数据报都将被设置 D F比特。如果某个中间路
由器需要对一个设置了 D F标志的数据报进行分片,它就
丢弃这个数据报,并产生一个 I C M P的, 不能分片, 差
错。
? 如果收到这个 I C M P差错,T C P就减少段大小并进行
重传。报文段大小被设置为下一跳的 M T U减去 I P和 T C
P的首部长度。
? 当由这个 I C M P差错引起的重传发生时,拥塞窗口不需
要变化,但要启动慢启动。
? 由于路由可以动态变化,因此在最后一次减少路径 M T U的
一段时间以后,可以尝试使用一个较大的值(直到等于对端
声明的 M S S或输出接口 M T U的最小值)。 RFC 11 9 1推
荐这个时间间隔为 1 0分钟
? 在对非本地目的地,默认的 M S S通常为 5 3 6字节,路径
M T U发现可以避免在通过 M T U小于 5 7 6(这非常罕见)
的中间链路时进行分片。
? 但为了能使路径 M T U更加有用和充分利用 M T U大于 5 7 6
的广域网,一个实现必须停止使用为非本地目的制定的 5 3 6
的 M T U默认值。
? M S S的一个较好的选择是输出接口的 M T U(当然要减去
I P和 T C P的首部大小)
? 大多数的实现都允许系统管理员改变这个默认的 M S S值
大分组还是小分组
? 常规知识告诉我们较大的分组比较好
? 因为发送较少的大分组比发送较多的小分组, 花费, 要少
(假定分组的大小不足以引起分片,否则会引起其他方面的
问题)。
? 这些减少的花费与网络(分组首部负荷)、路由器(选路的
决定)和主机(协议处理和设备中断)等有关。
? 但并非所有的人都同意这种观点
? 测量表明,分组并不一定是越大越好。
? 需要在更多的网络上对该领域进行更多的研究。
长肥管道
? 我们把一个 连接的容量 表示为
c a p a c i t y (b) = b a n d w i d t h (b/s) ×
ro u n d-t r i p t i m e ( s )
? 并称之为 带宽时延乘积
? 也可称它为 两端的管道大小
? 当这个乘积变得越来越大时,T C P的某些局限
性就会暴露出来。
多种网络的带宽时延乘积
长肥管道
? 具有大的带宽时延乘积的网络被称为长肥网络
( Long Fat Network,即 L F N)
? 一个运行在 L F N上的 T C P连接被称为长肥管道
? 管道可以被水平拉长(一个长的 RT T),或被垂
直拉高(较高的带宽),或向两个方向拉伸。
使用长肥管道会遇到多种问题
? T C P首部中 窗口大小 为 16 bit,从而将窗口限制在 6 5 5
3 5个字节内,现有的网络需要一个更大的窗口来提供最
大的吞吐量。用 窗口扩大选项 可以解决这个问题。
? 在一个长肥网络 L F N内的 分组丢失会使吞吐量急剧减少 。
如果只有一个报文段丢失,需要利用快速重传和快速恢复
算法来使管道避免耗尽。但是即使使用这些算法,在一个
窗口内发生的多个分组丢失也会典型地使管道耗尽(如果
管道耗尽了,慢启动会使它渐渐填满,但这个过程将需要
经过多个 RT T)。建议使用 有选择的确认 来处理一个窗
口发生的多个分组丢失。
? 许多 T C P实现对每个窗口的 RT T仅进行一次测量,它们
并不对每个报文段进行 RT T测量,在一个长肥网络 L F N
上 需要更好的 RT T测量机制 。采用 时间戳选项,它允许
更多的报文段被计时,包括重传。
? T C P对每个字节数据使用一个 32 bit无符号的序号来进
行标识,序号空间是有限的,相同序号 N在 M S L期间是
否被重用的问题,也就是说,网络是否足够快以至于在不
到一个 M S L的时候序号就发生了回绕。法:使用 T C P
的时间戳选项的 PAW S(Protection Against Wrapped
Sequence numbers)算法( 保护回绕的序号 )
T/TCP:为事务用的 TCP扩展
? T C P提供的是一种虚电路方式的运输服务。这种
虚电路服务非常适合诸如远程注册和文件传输之
类的应用。
? 但是,还有一些其他的应用进程被设计成使用事
务服务。一个事务就是符合下面这些特征的一个
客户请求及其随后的服务器响应。
? 1) 应该避免连接建立和连接终止的开销,在可能的时候,
发送一个请求分组并接收一个应答分组。
? 2) 等待时间应当减少到等于 RT T与 S P T之和。其中 RTT
(Round-Trip Ti m e )为往返时间,而 SPT (Server
Processing Ti m e )则是服务器处理请求的时间。
? 3) 服务器应当能够检测出重复的请求,并且当收到一个重
复的请求时不重新处理事务(避免重新处理意味着服务器
不必再次处理请求,而是返回保存的、与该请求对应的应
答)。
其中一个使用这种类型服务的应用就是域名服务
课下作业(必做)
1.查资料:拥塞控制
2.用协议分析工具进一步理解 TCP的工作机制和
实现细节
课下作业(选做)
1.编程实现一个 TCP服务器