三报文握手与四报文握手

早期的计算机被用来进行科学计算,在单机上即可完成,但为了满足不同主机间的数据交换,满足通信需求,TCP / IP 协议划分的五层模型物理层、数据链路层、网络层、传输层和应用层实现了互联网通信。

另外补充一句,叫做 TCP / IP 协议而不是 UDP / IP 协议是因为 UDP 协议太过简单了,只是将应用层交下来的报文添加 UDP 首部后即交付给 IP 层,所起到的作用仅仅是分发路由,将报文发送给对应的端口号;相比之下,TCP 协议则实现了面向连接的可靠交付,更能代表传输层协议的作用,也与网络层协议有一定的区分度(网络层协议为了设计尽量简单,采用了数据报服务,没有承担可靠交付的责任)。

TCP 是面向连接的协议,其连接的建立采用客户 / 服务器的方式,即 C / S 模式。C / S 模式实现了主机间应用进程之间的通信,它将客户进程和服务器进程区分开来,每一个客户进程都可以向服务器进程发送连接请求,进行双方的数据交换。

连接的过程被形象地比作握手,就像我走来伸手向你问候“你好”,你伸手回应“你好”。但我们现实生活中好像只进行了两次信息传送的过程就能建立连接,即两次问好,而 TCP 的连接需要三报文握手才能建立,原因是要解决网络信道不可靠的问题。网络信道本身是不可靠的,丢包的现象时有发生,所以才需要通过协议来实现可靠交付。

首先,服务器进程 B 创建传输控制块 TCB ,进入收听状态,等待客户进程的连接请求。客户进程 A 也是首先创建传输控制块 TCB 。

  • 第一次握手(连接请求报文段):A 主动发送连接请求,为自己随机选择一个初始序号 seq = x 。A 消耗一个序号。
  • 第二次握手(应答报文段):B 同意建立连接,回复确认号 ack = x + 1 ,以便核对,同时也为自己随机选择一个初始序号 seq = y 。B 消耗一个序号。
  • 第三次握手(确认报文段):A 收到确认,进入已建立连接状态,并发送确认号 ack = y + 1 。如果不携带数据则 A 不消耗序号。

B 收到确认后也进入已建立连接状态,TCP 连接成功建立,双方可进行数据交换。

 

Q1:序号是什么意思?

A1:文件分块通常不是顺序到达的,而且也方便对收到的文件进行确认。

Q2:为什么要让客户进程对应答报文段进行确认,进行第三次握手?B 在第一次接收请求报文段时就进入已建立连接状态,A 在接收到应答报文段后也进入已建立连接状态,双方也成功建立了连接不是吗?

A2:因为网络信道本身是不可靠的,如果 A 的连接请求报文丢失而未及时收到确认,就会再重传一个连接请求,此时当然也能成功建立连接。但是如果第一个连接请求报文段并没有丢失,而是在某些网络节点中长时间滞留,以致延误到连接释放以后的某个时间才到达 B 。本来这是个已失效的连接请求报文段,B 收到这个报文段后,会以为是 A 又发出了一次新的连接请求,如果不采用第三次报文握手,B 直接进入已建立连接状态,两者状态不对等,无法进行数据交换,B 的许多资源将白白浪费;而采用第三次握手,这个已失效的连接请求报文段送到 B 后,B 会发送应答报文段,现在 A 并没有发出建立连接的请求,自然不会理睬 B 的应答,B 收不到确认报文段,也就进入了关闭状态,没有为这个已失效的连接请求报文段建立起连接。

  • 第一次握手:
  • 第二次握手:
  • 第三次握手:
  • 第四次握手:

 

 

 

 

我们首先看一下客户端和服务器的具体连接过程,客户端首先向服务器发送请求报文段,服务器收到请求报文段后,如同意建立连接,则向客户端发送应答报文段,客户端接收到回应后进入已建立连接状态,并且还要再给服务器发送确认报文段,服务器接收到确认后也进入已建立连接状态。我们将这三个过程叫做三报文握手,因为总共发送了三个报文建立了连接。客户端的请求报文段的首部置同步位 SYN = 1 ,同时随机选择一个初始序号 seq = x ;服务器的应答报文段首部中的同步位 SYN 和确认位 ACK 都置为 1 ,确认号是 ack = x + 1 ,同时也为自己选择一个随机初始序号 seq = y ;客户端的确认报文段的首部置确认位 ACK = 1 ,确认号 ack = y + 1 ,而自己的序号 seq = x + 1 。TCP 的标准规定,确认报文段可以携带数据,但如果不携带数据则不消耗序号,即下一个数据报文段的序号仍是 seq = x + 1 。

强调序号的原因是发送的数据报到达的先后顺序不同,TCP 协议需要处理数据报乱序问题,即通过滑动窗口的方式实现数据报的按序到达。

需要注意的是,TCP 连接是全双工的,因此不需要特地区分哪个是数据的发送方哪个是接收方,接收方需要在建立连接后的接收数据过程中不断对数据报文段进行确认(当然是根据接收窗口的情况进行确认)。确认号就是表示该确认号之前的所有数据均已正确收到,希望下次接收序号为该确认号的数据。

确认报文段不携带数据则不消耗序号我们也可以来分析一下加深印象,前两次握手分别消耗了一个各自的序号,因为分别发送了各自的初始序号用以接收的确认,而第三次握手只有一个确认号,服务器不需要再对这个确认号再进行一次确认,除非有新的数据发送过来,此时客户端才需要消耗序号。

那么为什么需要让客户端对服务器发来的应答报文段进行确认,进行第三次握手呢?服务器在第一次接收请求报文段时就进入已建立连接状态,客户端在接收到应答报文段时也进入已建立连接状态,双方也成功建立了连接不是吗?

因为网络信道本身是不可靠的,客户端发送的请求报文段有可能在网络中滞留或丢失,如果客户端的请求报文段丢失而没有及时收到服务器的确认,就会再重传一个连接请求,此时当然也能成功建立连接,但是如果第一个请求报文段并没有丢失,而是在某个网络节点中滞留,导致服务器会收到两个来自客户端的连接请求。如果是两次握手,服务器会同时为客户端建立两个已连接状态,其中一条连接会一直等待客户端发来数据,而那一条是无效连接,服务器的许多资源将白白浪费;如果是三次握手,服务器会为这两个连接请求分别进行应答,而客户端认为只有一个连接,只会为其中一个应答报文段进行确认,成功建立连接。因此连接确认的过程中使用三报文握手。

处于连接状态的客户端和服务端,都可以发起关闭连接请求,此时需要四报文握手进行释放连接。假设客户端主动发起连接关闭请求,向服务器发送连接释放报文段,并停止再发送数据,关闭 TCP 连接,进入终止等待 1 状态;服务器接收到连接释放报文段后会立即发送确认报文段,此时从客户端到服务器方向的连接就关闭了,即客户端已经没有数据要发送给服务器了,TCP 连接处于半关闭状态,但从服务器到客户端方向的连接并未关闭,并且这个状态可能会持续一段时间,所以服务器可以在这段时间内继续发完剩余的数据;客户端在接收到服务器的确认报文段后就进入终止等待 2 状态,等待服务器发出的连接释放报文段;若服务器已经没有要发送的数据了,就会发送连接释放报文段给客户端,并进入最终确认状态,等待客户端的确认;客户端在接收到服务器的连接释放报文段后,必须对此发出确认报文段,必须经过时间等待计时器设置的时间 2MSL 后才能进入到 CLOSED 状态,当客户端撤销相应的传输控制块 TCB 后,就结束了这次的 TCP 连接;服务器只要接到了确认报文段后就会进入 CLOSED 状态,同样,当服务器撤销相应的传输控制块 TCB 后,就结束了这次的 TCP 连接。上述的 TCP 连接释放过程是四报文握手。

posted @   HanselHuang  阅读(1125)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示