TCP连接
TCP连接提供的是全双工服务,TCP连接也是点对点的。
发起连接的进程被称为客户进程,另一个进程称为服务器进程。
三次握手:两个主机间发送了三个报文段,第三个报文段中包含应用层数据也即有效载荷
TCP可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度MSS。MSS的典型值为1460字节。
TCP为每块客户数据配上一个TCP首部,从而形成多个TCP报文段。,网络层将其分别封装在网络层IP数据报中。当TCP在另一端接收到一个报文段后,该报文段的数据就被放入该TCP连接的接收缓存中。
TCP连接的每一段都有各自的发送缓存和接收缓存。
TCP报文段结构
TCP报文段由首部字段和一个数据字段组成。TCP通常是将该文件划分成长度为MSS的若干块。
TCP的首部:
-
源端口号和目的端口号:被用于多路复用/分解来自或送到上层应用的数据
-
检验和字段:和UDP相同
-
32bit的序号字段
-
32bit的确认号字段
-
16bit的接收窗口字段:指示接收方愿意接受的字节数量,用于流量控制
-
4bit的首部长度字段:指示了以32bit的字为单位的TCP首部长度,首部长度可变,通常选项长度为空,故TCP的首部一般为20字节。
-
可选与变长的选项字段:用于协调MSS或者用作窗口调节因子时使用
-
6bit的标志字段
-
ACK:用于指示确认字段中的值是有效的,即该报文段包括一个对已被成功接收报文段的确认
-
RST、SYN和FIN:用于连接建立和拆除
-
PSH:指示接收方应立即将数据交给上层
-
URG:指示报文段里存在着被发送端的上层实体置为紧急的数据
-
-
16bit的紧急数据指针字段:指出紧急数据的最后一个字节,当紧急数据存在并给出指向紧急数据尾的指针的时候,TCP必须通知接收端的上层实体
序号和确认号
TCP把数据看成一个无结构的、有序的字节流。序号是建立在传送的字节流中,而不是建立在传送的报文段的序列之上。
一个报文段的序号是该报文段首字节的字节流编号。
主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的序号。
TCP只确认该流中至第一个丢失字节为止的字节,所以TCP被称为提供累积确认。一条TCP连接均可以随机的选择初始序号。
Telnet:序号和确认号的一个学习案例
发起会话的是客户。
第一个报文段:
- 由客户发往服务器
- 序号字段是42,由于客户还没有接收到来自服务器的任何数据,确认好字段是79
第二个报文段:
- 由服务器发向客户
- 为该服务器所收到数据提供一个确认
- 在确认号字段里填入43,代表42及以前的字节已经成功收到,正在等待42的出现
- 序号为79,是该TCP连接上从服务器到客户的数据流的起始序号,也是服务器要发送的第一个字节的数据
- 客户到服务器的数据的确认被装载在一个承载服务器到客户的数据的报文段中,这种确认被称为是被捎带在服务器到客户的数据报文段中的
第三个报文段:
- 从客户发往服务器
- 确认已从服务器收到的数据,该报文段的数据字段为空:确认信息没有被从客户到服务器的数据所捎带
- 确认号字段填入80,因为客户已经收到了字节流中序号为79及以前的字节,正在等待80
往返时间的估计与超时
超时间隔必须大于该连接的往返时间,即从一个报文段发出到它被确认的时间,否则会造成不必要的重传。
估计往返时间
报文段的样本RTT是从某报文段被发出(交给IP)到对该报文段的确认被收到之间的时间量。TCP在任意时刻,仅为一个已发送的但目前未被确认的报文段估计SampleRTT,从而产生一个接近每个RTT的新SampleRTT值。
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
,
α
=
0.125
EstimatedRTT=(1-\alpha)·EstimatedRTT+\alpha·SampleRTT, \alpha=0.125
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
,
α
=
0
.
1
2
5
RTT偏差
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|
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
∣
用于估算偏离程度
β
=
0.25
\beta=0.25
β
=
0
.
2
5
设置和管理重传时间间隔
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·DevRTT
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
出现超时后,
T
i
m
e
o
u
t
I
n
t
e
r
v
a
l
TimeoutInterval
T
i
m
e
o
u
t
I
n
t
e
r
v
a
l
会加倍,以免即将被确认的后继报文过早出现超时
可靠数据传输
TCP发送方的三个与发送和重传有关的主要事件:
-
从上层应用程序接收数据
- 发生的话,TCP将数据封装在一个报文段中,并把报文段交给IP,每一个报文段都包括一个序号
-
定时器超时:定时器的过期间隔是
Ti
m
e
o
u
t
I
n
t
e
r
v
a
l
TimeoutInterval
T
i
m
e
o
u
t
I
n
t
e
r
v
a
l
,通过重传引起超时的报文段来响应超时事件,然后TCP重启定时器 - 收到ACK:TCP将ACK的值y与它的变量SendBase进行比较,TCP状态变量SendBase是最早未被确认的字节的序号。由于TCP采用累积确认,y确认了y之前的所有字节都已经收到,如果y>SendBase,则需要更新SendBase变量,如果有未被确认的报文段,重新更新定时器
一些情况
由于确认丢失而重传
报文段100没有重传
假设在超时之前这两个报文段中没有一个确认报文到达主机A,当超时事件发生时,主机A重传序号92的第一个报文段,
并且重启定时器
,只要第二个报文段的ACK在新的超时发生以前到达,第二个报文段不会被重传。
累计确认避免第一个报文段重传
第一个报文段的确认报文在网络中丢失,但在超时事件发生之前主机A收到一个确认号为120的确认报文,主机A因而知道B已经收到了119及之前的所有字节,故主机A不会重传两个报文段中的任何一个。
超时间隔加倍
TCP重传具有最小序号的还未被确认的报文段。每次TCP重传时都会将下一次的超时间隔设为先前值的两倍。这种修改提供了一个形式受限的拥塞控制。
快速重传
发送方通常可在超时时间发生之前通过冗余ACK来检测丢包情况,冗余ACK是再次确认某个报文段的ACK,而发送方先前已经收到对该报文段的确认。
事件 | TCP接收方动作 |
---|---|
具有所期望序号的按序报文段到达。所有在期望序号及以前的数据都已经被确认 | 延迟的ACK,对另一个按序报文段的到达最多等待500ms。如果下一个按序报文段在这个时间间隔内没有到达,则发送ACK |
具有所期望序号的按序报文段到达,另一个按序报文段等待ACK传输 | 立即发送单个累积ACK,以确认两个按序报文段 |
比期望序号大的失序报文段到达,检测出间隔 | 立即发送冗余ACK,指示下一个期待字节的序号(为间隔的低端的序号) |
能部分或完全填充接收数据间隔的报文段到达 | 倘若该报文段起始于间隔的低端,则立即发送ACK |
TCP不使用否定确认,对已经接收到的最后一个按序字节数据进行重复确认。
如果TCP发送方接收到对相同数据的3个冗余ACK,它把这当做一种指示,说明跟在这个已经被确认过3次的报文段之后的报文段已经丢失,执行快速重传,即在该报文段的定时器过期之前重传丢失的报文段。
是回退N步还是选择重传
TCP发送方只需要维持已发送过但未被确认的字节的最小序号SendBase和下一个要发送的字节的序号NextSeqNum。许多TCP实现会缓存正确接收且时序的报文段。
TCP的一种修改意见是选择确认,允许TCP接收方有选择的确认失序报文段,而不是累积的确认最后一个正确接收的有序报文段。
流量控制
流量控制:消除发送方使接收方缓存溢出的可能性,是一个速度匹配服务,发送方的发送速率与接收方应用程序的读取速率匹配
拥塞控制:发送方的控制
TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。接收窗口用于给发送方一个指示:该接收方还有多少可用的缓存空间,在连接两端的发送方都各自维护一个接收窗口。
当主机B的接收窗口为0时,主机A继续发送只有一个字节数据的报文段。这些报文段将会被接收方确认。最终缓存将开始清空,并且确认报文里将包含一个非0的rwnd值
TCP连接管理
三次握手:建立连接
- Step 1:客户端TCP向服务器端TCP发送一个特殊TCP报文段,不含应用层数据,首部的标志位SYN被置为1.这个特殊报文段也被称为SYN报文段。客户端会随机的选择一个初始序号client_isn,并将此编号放置于该起始的TCP SYN报文段的序号字段中
-
Step 2:服务器从IP数据报中提取出TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段。这个报文段不包含应用层数据:
- SYN 比特被置为1
- TCP报文段首部的确认号字段为client_isn+1
- 服务器初始序号为server_isn,放置到首部的序号字段中
- 这个报文段被称为SYNACK报文段
-
Step 3:收到SYNACK报文段后,客户端给该连接分配缓存和变量,客户向服务器发送一个报文段,这个报文段确认服务器的允许连接的报文段,SYN比特被置为0,
可以携带客户到服务器的数据
三次握手后,以后的每一个报文段中,SYN都被置为0
四次挥手:关闭连接
一条TCP连接中的两个任一进程都能终止该连接,连接结束后,主机中的缓存和变量会被释放。
- Step 1:客户TCP向服务器进程发送一个特殊的TCP报文段,首部的一个标志位为FIN设置为1
- Step 2:服务器接收到报文段后,向发送方回送一个确认报文段
- Step 3:服务器发送终止报文段,FIN被设置为1
- Step 4:客户对终止报文段确认
TCP状态
客户端TCP状态
CLOSED-SYN_SENT-ESTABLISHED-FIN_WAIT_1-FIN_WAIT_2-CLOSED
SYN Cookie 解决洪泛攻击:
- 收到一个SYN报文段时,先生成一个初始TCP序列号,被称为Cookie,服务器发送具有这种特殊序列号的SYNACK分组。服务器不记忆该Cookie或任何对应于SYN的状态信息
- 客户如果合法,返回一个ACK报文段。借助cookie验证是否合法,cookie的计算和核算是相同的散列函数。
服务器端TCP状态
CLOSED-LISTEN-SYN_RCVD-ESTABLISHED-CLOSN_WAIT-LAST_WAIT-CLOSED
当主机接收到一个TCP报文段,其端口号或源IP地址和主机上套接字都不匹配时,主机会向源发送一个特殊重置报文段,该TCP报文段将RST标志位置为1
当主机接收到一个UDP分组,其端口号和主机上套接字都不匹配时,主机会向源发送一个ICMP数据报