TCP
是面向连接的协议,它基于运输连接来传送 TCP
报文段。
TCP
运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。
TCP
运输连接有以下三个阶段
- 建立
TCP
连接:通过 “三报文握手” 建立TCP
连接 - 数据传送:也就是基于已建立的
TCP
连接建立可靠的数据传输 - 释放
TCP
连接:也就是数据传输结束后还要通过 “四报文挥手” 来释放TCP
连接
TCP
的运输连接管理就是使运输连接的建立和释放都能正常地进行
。
TCP
的连接建立要解决以下三个问题:
-
使
TCP
双方能够确知对方的存在
; -
使
TCP
双方能够协商一些参数
(如最大窗口值、是否使用窗口扩大选项和时间戳选项以及服务质量等); -
使
TCP
双方能够对运输实体资源
(如缓存大小、连接表中的项目等)进行分配。
1、TCP 使用 “三报文握手” 建立连接的具体过程
具体流程图
如下所示
TCP
客户:其中一台主机中的某个应用进程主动发起TCP
连接的建立TCP
服务器:另一台主机被动等待建立TCP
连接的应用进程
可以将 TCP
建立连接的过程比喻为 “握手”
“握手” 需要在 TCP
客户和服务器之间交换三个 TCP
报文段
最初,两端的 TCP
进程都处于
关闭状态
\color{blue}关闭状态
关闭状态
一开始,TCP
服务进程首先创建传输控制块
-
用来存储
TCP
连接中的一些重要信息。例如:
TCP
连接表,指向发送和接收缓存的指针,指向重传队列的指针,当前的发送和接收序号等
之后,就准备接收 TCP
客户进程的连接请求
- 此时,
TCP
服务器就进入 监听状态 \color{blue}监听状态 监听状态,等待TCP
客户进程的连接请求
TCP
服务器进程是被动等待来自 TCP
客户进程的连接请求,而不是主动发起
- 因此,被称为
被动打开连接
TCP
服务进程也是首先创建传输控制块
然后再打算建立 TCP
连接时,向 TCP
服务器进程发送 TCP
连接请求报文段
- 并进入 同步已发送状态 \color{blue}同步已发送状态 同步已发送状态
TCP
连接请求报文段首部中的同步位 SYN
被设置为
1
1
1
- 表明这是一个
TCP
连接请求报文段
序号字段 seq
被设置了一个初始值
x
x
x
- 作为
TCP
进程所选择的初始序号
注意
:TCP
规定 SYN
为
1
1
1 的报文段不能携带数据,但要消耗掉一个序号
由于 TCP
连接建立是由 TCP
客户主动发起的
- 因此称为主动打开连接
TCP
服务器进程收到 TCP
请求报文段后
- 若同意建立连接,则向
TCP
客户进程发送TCP
连接请求确认报文段,并进入 同步已接受状态 \color{blue}同步已接受状态 同步已接受状态
该报文段首部中的同步位 SYN
和确认位 ACK
都设置为
1
1
1
- 表明这是一个
TCP
连接请求确认报文段
序号字段 seq
被设置为初始值
y
y
y
- 作为
TCP
服务器进程所选择的初始序号
确认号字段 ack
的值被设置为
x
+
1
x + 1
x+1
- 这是对
TCP
客户进程所选择的初始序号的确认
注意
:该报文段也不能携带数据,因为它是 SYN
被设置为
1
1
1 的报文段
- 但同样要消耗掉一个序号
TCP
客户进程收到 TCP
连接请求确认报文后
-
还要向
TCP
服务器进程发送一个普通的TCP
确认报文段 -
并进入 连接已建立状态 \color{blue}连接已建立状态 连接已建立状态
该报文段首部中的确认位 ACK
设置为
1
1
1
- 表明这是一个不同的
TCP
确认报文段
序号字段 seq
被设置为初始值
x
+
1
x + 1
x+1
- 这是因为
TCP
客户进程发送的第一个TCP
报文段的序号为 x x x,并且不携带数据 - 因此,第二个报文段的序号为 x + 1 x + 1 x+1
注意
:TCP
规定普通的 TCP
确认报文段可以携带数据
-
但若不携带数据,则不消耗序号
在这种情况下,所发送的下一个数据报文段的序号仍是 x + 1 x+1 x+1
确认号字段 ack
的值被设置为
y
+
1
y + 1
y+1
- 这是对
TCP
服务器进程所选择的初始序号的确认
TCP
服务器进程收到该确认报文段后
- 也进入 连接已建立状态 \color{blue}连接已建立状态 连接已建立状态
现在 TCP
双方都进入了连接已建立状态,它们可以基于已建立好的 TCP
连接进行可靠的数据传输了
2、为什么要 “三报文握手”
思考?为什么 TCP
客户进程最后还要发送一个普通的 TCP
确认报文段呢?
- 这是否多余?
- 即:能否使用 “两报文握手” 建立连接呢?
否定的!
假设 TCP
客户进程发出一个 TCP
连接请求报文段。
-
但该报文段再某些网络节点长时间滞留了
这必然会造成该报文段的超时重传
假设重传的报文段被 TCP
服务进程正常接收
TCP
服务进程给 TCP
客户进程发送一个 TCP
连接请求确认报文段
- 并进入 连接已建立状态 \color{blue}连接已建立状态 连接已建立状态
注意
:由于改为两报文握手,TCP
服务器进程发送 TCP
连接请求确认报文段后进入
连接已建立状态
\color{blue}连接已建立状态
连接已建立状态
- 而不像 “三报文握手” 那样进入
同步已接受状态
\color{blue}同步已接受状态
同步已接受状态,并等待
TCP
客户进程发来针对TCP
连接请求确认报文段的普通确认报文段
TCP
客户进程收到 TCP
连接请求确认报文后,进入 TCP
连接已建立状态
- 但不会给
TCP
服务器进程发送针对该报文段的普通确认报文段
现在 TCP
双方都处于
连接已建立状态
\color{blue}连接已建立状态
连接已建立状态,他们可以相互传输数据,之后可以通过 “四报文挥手” 来释放连接
TCP
双方都进入了
关闭状态
\color{blue}关闭状态
关闭状态
一段时间后,之前滞留在网络中的那个失效的 TCP
连接请求报文段到达了 TCP
服务器进程
TCP
服务器进程会误认为这是 TCP
客户进程又发起了一个新
的 TCP
连接请求
- 于是
TCP
服务进程给TCP
客户进程发送一个TCP
连接请求确认报文段,并进入 连接已建立状态 \color{blue}连接已建立状态 连接已建立状态
该报文段到达 TCP
客户进程并没有
发起新的 TCP
连接请求,并且处于关闭状态
- 因此,不会理会该报文
但 TCP
服务器进程已进入已连接状态,它认为新的 TCP
已建立好了
- 并一直等待
TCP
客户进程发来数据,这将白白浪费TCP
服务器进程所在主机的很多资源
综上: 这是为了防止已失效的连接请求报文段又传送到了 TCP 服务器,因而导致错误 \color{red}这是为了防止已失效的连接请求报文段又传送到了\texttt{TCP}服务器,因而导致错误 这是为了防止已失效的连接请求报文段又传送到了TCP服务器,因而导致错误