-
Notifications
You must be signed in to change notification settings - Fork 32
/
4.2、TCP 协议.md
301 lines (159 loc) · 14.2 KB
/
4.2、TCP 协议.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# TCP
* 传输控制协议(Transmission Control Protocol ,TCP )是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF 的RFC 793 定义。
* TCP 与UDP 同处于传输层,是TCP/IP
## 特点
* TCP 是**面向连接**(建立好连接才发送,即三次握手完就说明建立好连接了)的传输层协议。
* 每一条 TCP 连接只能有**两个端点**(endpoint),每一条TCP 连接只能是点对点的(一对一)。
* TCP 提供**可靠交付**的服务。
* TCP 提供**全双工**通信。
* **面向字节流**。
传输过程
<img src="https://img-blog.csdnimg.cn/20210112201159650.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104115422275" width="40%"/>
* TCP 连接是一种虚连接而不是真正的物理连接。
* TCP 不关心应用程序一次把多长的报文发送到TCP 的缓存中。
* TCP 根据对方给出的窗口值和当前网络拥塞的程度来决定一个报文段应包含多少个字节(UDP 发送的报文长度是应用进程给出的)。
* TCP 可把太长的数据块划分短一些再传送,也可等待积累足够多的字节后再构成报文段发送出去。
TCP 连接的建立都是采用客户服务器方式:
* 主动发起连接建立的应用进程称为客户端 (client) 。
* 被动等待连接建立的应用进程称为服务器 (server) 。
## 报文结构
<img src="https://img-blog.csdnimg.cn/20210112201322352.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104115935388" width="50%"/>
源端口和目的端口字段(各占 2 字节)
* 端口是传输层与应用层的服务接口。传输层的复用和分用功能都要通过端口才能实现。
确认号字段(占 4 字节)
* 是期望收到对方的下一个报文段的数据的第一个字节的序号。
数据偏移(即首部长度)(占 4 位)
* 它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。
* “ 数据偏移” 的单位是32 位字(以 4 字节为计算单位)。
保留字段(占 6 位)
* 保留为今后使用,但目前应置为 0 。
紧急 URG
* 当 URG = 1 时,表明紧急指针字段有效。
* 它告诉系统此报文段中有紧急数据,应尽快传送( 相当于高优先级的数据)
确认 ACK
* 只有当 ACK = 1 时确认号字段才有效。当ACK = 0 确认号无效。
推送 PSH (PuSH)
* 接收 TCP 收到 PSH = 1 的报文段,就尽快地交付接收应用进程,而不再等到整个缓存都填满了后再向上交付。
复位 RST (ReSeT)
* 当 RST = 1 时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。
同步 SYN
* 同步 SYN = 1 表示这是一个连接请求或连接接受报文。
终止 FIN (FINis)
* FIN = 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。
窗口字段 (占 2 字节)
* 用来让对方设置发送窗口的依据,单位为字节。
检验和(占 2 字节)
* 检验和字段检验的范围包括首部和数据这两部分。
* 在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
紧急指针字段 (占 16 位)
* 指出在本报文段中紧急数据共有多少个字节(紧急数据放在本报文段数据的最前面)。
选项字段(长度可变)
* MSS
* TCP 最初只规定了一种选项,即最大报文段长度 MSS 。
* MSS 告诉对方 TCP : “ 我的缓存所能接收的报文段的数据字段的最大长度是 MSS 个字节。”
* MSS (Maximum Segment Size) 是 TCP 报文段中的 数据字段的最大长度。数据字段加上 TCP 首部才等于整个的 TCP 报文段。
* 窗口扩大选项(占 3 字节)
* 其中有一个字节表示移位值 S 。
* 新的窗口值等于 TCP 首部中的窗口位数增大到 (16 + S) ,相当于把窗口值向左移动 S 位后获得实际的窗口大小。
* 时间戳选项 (占 10 字节)
* 其中最主要的字段时间戳值字段( 4 字节)和时间戳回送回答字段( 4 字节)。
* 选择确认选项
* 有选择的确认收到的某些报文,以便提高效率。
填充字段
* 这是为了使整个首部长度是 4 字节的整数倍。
## 连接
TCP 连接
* TCP把连接作为最基本的抽象。
* 每一条TCP 连接有两个端点。
* TCP连接的端点叫做套接字(socket)或插口。
* 端口号拼接到(contatenated with) IP 地址即构成了套接字
每一条 TCP 连接唯一地被通信两端的两个端点(即两个套接字)所确定。
* 即:TCP 连接 ::= {socket1, socket2}= {(IP1: port1), (IP2: port2)}
TCP 连接的三个阶段
* 传输连接就有三个阶段,即:连接建立、数据传送和连接释放。传输连接的管理就是使传输连接的建立和释放都能正常地进行。
* 连接建立过程中要解决以下三个问题:
* 要使每一方能够确知对方的存在。
* 要允许双方协商一些参数(如最大报文段长度,最大窗口大小,服务质量等)。
* 能够对传输实体资源(如缓存大小,连接表中的项目等)进行分配。
TCP 连接的建立
* TCP 连接的建立过程也被称为三次握手
* 第一次 : 客户端 -> 服务器。客户端向服务器提出连接建立请求,即发出同步请求报文。
* 第二次 : 客户端 <- 服务器。服务器收到客户端的连接请求后,向客户端发出同意建立连接的同步确认报文。
* 第三次 : 客户端 -> 服务器。客户端在收到服务器的同步确认报文后,向服务器发出确认报文。
* 当服务器收到来自客户端的确认报文后,连接即被建立
建立过程说明
<img src="https://img-blog.csdnimg.cn/20210112201356876.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104135056841" width="50%" />
* 客户端A 向服务器发出连接请求报文, SYN=1 ,选择序号 seq=x
* 服务器B 的 TCP 收到连接请求报文后,如同意,则发回确认。
* 服务器B 在确认报文中将 SYN = 1 , ACK = 1 ,且其确认号 ack =x+1 ,自己选择的序号 seq = y
* 客户端A 收到B 的确认报文后向服务器B 发出确认报文,即 ACK = 1 ,确认号 ack = y+1 。
* 客户端A 的 TCP 通知上层应用进程,连接已经建立。
* 服务器B 的 TCP 收到客户端A 的确认后,也通知其上层应用进程:连接已经建立。
* 开始传送数据
TCP 连接的释放
* TCP 连接释放的建立过程也被称为四次挥手
* 第一次 : 客户端 -> 服务器。客户端向服务器发出一个连接释放报文。
* 第二次 : 客户端 <- 服务器。服务器收到客户端的释放连接请求后,向客户端发出确认报文。
* 第三次 : 客户端 <- 服务器。服务器在发送完最后的数据后,向客户端发出连接释放确认报文。
* 第四次 : 客户端 -> 服务器。客户端在收到服务器连接释放报文后,向服务器发出确认报文。
释放过程说明
<img src="https://img-blog.csdnimg.cn/20210112201419268.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104140039815" width="50%" />
* 数据传输结束后,通信的双方都可释放连接。现在 A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP连接。
* A 把连接释放报文段首部的 FIN = 1 ,其序号seq = u ,等待 B 的确认。
* B 发出确认, ack = u+1 ,而这个报文段自己的序号 seq = v 。
* TCP 服务器进程通知高层应用进程。
* 从 A 到 B 这个方向的连接就释放了, TCP 连接处于 半关闭 状态。 B若发送数据, A 仍要接收
* 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP
* A 收到连接释放报文段后,必须发出确认,且置 ACK = 1 , ack=w+1 ,
TCP 连接必须经过时间 2MSL 后才真正释放掉
<img src="https://img-blog.csdnimg.cn/20210112201449824.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104140825725" width="50%" />
* MSL (Maximum Segment Lifetime )是任何报文在网络上的存在的最长时间,超过这个时间报文将被丢弃。
* RFC793 中规定MSL 为2 分钟,不同的操作系统在实现时各不相同,常用的有30 秒、1 分钟、2 分钟不等。
* A 必须等待 2MSL 的时间的原因:
* 第一,为了保证客户端发送的最后一个 ACK 报文段能够到达服务器。
* 第二,防止 “ 已失效的连接请求报文段 ” 出现在本连接中。客户端在发送完最后一个 ACK 报文段后,再经过时间 2MSL ,就可以使本连接持续的时间内所产生的所有报文段,都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
## 计数器
* 为了保证传输的可靠性和协议栈的稳定,一条TCP 连接可以用多达9 种不同类型的定时器为其保驾护航。
* 这些定时器包括:重传计时器,坚持计时器, ER 延迟计时器, PTO 计时器,ACK 延迟计时器, SYNACK 计时器,保活计时器,时间等待计时器, FIN_WAIT2 计时器等。
* TCP 要保证正常工作,至少应该有四种计时器:重传计时器、持久计时器、保活计时器和时间等待计时器。
重传计时器
* TCP 是一种能提供可靠传输的通信协议,其可靠性来自于协议的确认重传机制。
* 当接收端收到一个TCP 报文后,就会向发送方发出一个确认报文,并指示对方下次传送数据的起始位置。
* 由于网络的不确定性,发送的数据报文和确认报文都有可能在传输过程中丢失。
* 重传计时器(Retransmission Timer ),当发送方发出数据报文后即启动该计时器(一般为60 秒):
* 在设定时间截至之前收到确认报文,则传输成功,撤销计时器;否则,传输失败,重新发送数据报文。
坚持计时器
* 当接收方发出一个零窗口确认报文,发送方立即停止发送数据报文直到接收方发出非零窗口的确认报文。
* 由于TCP 不会对确认报文进行确认,因此接收方在发出非零窗口确认报文后即进入等待发送方发送数据报文。
* 如果此确认报文在中途丢失,在通信会陷入死锁。
* 坚持计时器(Persistent Timer )即为破解此死锁而设定。
* 当发送方收到一个零窗口确认时,即启动坚持计时器
* 若在设定时间到达之前收到接收方的非零窗口确认报文,则撤销该计时器,恢复正常发送数据报文。
* 若设定时间到达仍未收到接收方的非零窗口确认报文,则发送方发出一个只有一个字节数据的探测报文并消耗一个序号,但该序号会被确认报文所忽略。
* 探测报文的目的,即提醒接收方:确认丢失,重新发送。
* 坚持计时器的值与重传计时器相同。若在截止时间后没有收到接收方的非零窗口确认报文,则发送另一个探测报文,并加倍设置坚持计时器值,如此反复直到收到接收方的非零窗口确认报文为止。
* 坚持计时器的值有最大值限制(门限值,通常为60 秒)。
保活计时器
* 保活计时器(keepalive timer )用于判断两个TCP 端点之间长久的连接是否正常。
* 当客户端与服务器建立了TCP 连接后,保活计时器即被激活,并设置计时值(通常为2 小时)。每当服务器收到来自客户端的报文,即重置计时器。
* 当计时截止后仍未收到客户端的报文,则服务器将向客户端发出探测报文,并每隔75 秒发送一个探测报文。
* 如果发出10 个探测报文后依然没有得到客户端的确认报文,则服务器假定客户端遇到了故障,,于是强制关闭这条连接。
* 当服务器发送探测报文时,客户端可能处于四种不同的状态:
* 客户端运行正常
* 一切正常,客户端能收到服务器的探测报文并发出响应确认报文,服务器重置保活计时器。
* 客户端已经崩溃
* 客户端可能已经关闭或正在重新启动,无法接收和响应服务器的探测报文。服务器在10 个探测报文以后即终止与客户端的连接。
* 客户端已经崩溃并重启
* 客户端已经重启,在收到服务器的探测报文后,客户端将返回一个RST 报文。服务器在收到RST 报文后即关闭连接。
* 网络链路故障
* 客户端可能依然在正常运行,但无法收到来自服务器的探测报文,也无法向服务器发送数据报文。由于无法判断是链路故障还是客户端故障,因此服务器终止连接。
时间等待计时器
* 时间等待计时器(Time_Wait Timer )也叫2MSL 计时器,是TCP 终止连接时启动的计时器。
* 当主动关闭的一方收到被动关闭一方FIN=1 的控制报文信息后状态由FIN-WAIT-2 变为TIME-WAIT ,并发送一个ACK 确认报文,同时启动计时器开始计时。
* 如果被动关闭的一方在2MSL 后没有发送重传请求,主动关闭的一方即认为对方已经收到ACK 报文并关闭了连接,于是主动关闭的一方才把连接关闭。
* 设置这个计时器的主目的是为了能够正常关闭服务端的连接!
## 状态变迁
<img src="https://img-blog.csdnimg.cn/20210112201516833.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzkzNDYwNw==,size_16,color_FFFFFF,t_70" alt="image-20210104144249396" width="60%" />
* 红实线箭头 表示客户进程的正常变迁。
* 蓝虚线箭头 表示服务器进程的正常变迁。
* 黑细线箭头 表示异常变迁。