当前位置: 首页 > news >正文

TCP三次握手与四次挥手

TCP三次握手与四次挥手:深入理解网络连接的建立与终止

在网络通信中,TCP(传输控制协议)是确保数据可靠传输的核心协议。作为一名网络工程师或开发者,深入理解TCP的三次握手和四次挥手过程是必备技能。本文将带您详细了解这两个关键过程,以及它们背后的设计原理。

TCP连接的本质

在深入握手和挥手过程之前,我们需要先理解TCP连接的本质。TCP连接用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合包括Socket、序列号和窗口大小

TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。与UDP不同,TCP在通信前需要先建立连接,通信结束后还需要释放连接,这正是通过"三次握手"和"四次挥手"来完成的

TCP三次握手:连接的建立

三次握手的基本过程

TCP三次握手是指在建立TCP连接时,客户端和服务器之间需要交换三个报文段才能成功建立连接的过程。这个过程不仅确保了通信双方的发送和接收能力,还协商了一些连接参数,如初始序列号等。

第一次握手:客户端发送SYN包

  • 客户端向服务器发送一个SYN(同步)报文段,表明客户端请求建立连接

  • 这个报文段中,SYN标志位被设置为1,序列号(seq)被设置为一个随机值x(客户端的初始序列号ISN)

  • 此时,客户端进入SYN_SENT状态,等待服务器的确认

第二次握手:服务器响应SYN-ACK包

  • 服务器收到客户端的SYN报文段后,如果同意建立连接,会向客户端发送一个SYN+ACK报文段

  • 在这个报文段中,SYN标志位和ACK标志位都被设置为1,确认号(ack)被设置为客户端的序列号加1(即x+1),序列号(seq)被设置为一个随机值y(服务器的初始序列号ISN)

  • 此时,服务器进入SYN_RECEIVED状态,等待客户端的确认

第三次握手:客户端发送ACK包

  • 客户端收到服务器的SYN+ACK报文段后,会向服务器发送一个ACK报文段,表明客户端已收到服务器的SYN+ACK报文段

  • 在这个报文段中,ACK标志位被设置为1,确认号(ack)被设置为服务器的序列号加1(即y+1),序列号(seq)被设置为x+1

  • 此时,客户端进入ESTABLISHED状态

  • 服务器收到客户端的ACK报文段后,也进入ESTABLISHED状态,表示连接已成功建立

为什么是三次握手?不是两次或四次?

这是面试中最常见的问题之一。三次握手的设计是为了解决几个关键问题:

1. 防止历史重复连接初始化造成的混乱

这是三次握手的主要原因。考虑一个场景:客户端先发送了SYN(seq=90)报文,然后客户端宕机了,而且这个SYN报文还被网络阻塞了,服务端并没有收到。接着客户端重启后,又重新向服务端建立连接,发送了SYN(seq=100)报文。

在网络拥堵情况下,一个「旧SYN报文」可能比「最新的SYN」报文早到达服务端。此时服务端就会回一个SYN+ACK报文给客户端,此报文中的确认号是91(90+1)。客户端收到后,发现自己期望收到的确认号应该是100+1,而不是90+1,于是就会回RST报文。服务端收到RST报文后,就会释放连接。

2. 同步双方的初始序列号

TCP协议的通信双方都必须维护一个序列号,序列号是可靠传输的关键因素。三次握手过程可以确保双方的初始序列号都被正确同步。

3. 避免资源浪费

如果只有两次握手,当客户端发送的SYN报文在网络中阻塞,客户端没有接收到ACK报文,就会重新发送SYN。由于没有第三次握手,服务端不清楚客户端是否收到了自己回复的ACK报文,所以服务端每收到一个SYN就只能先主动建立一个连接,这会造成多个冗余的无效链接,造成不必要的资源浪费。

TCP四次挥手:连接的优雅终止

四次挥手的基本过程

TCP四次挥手是TCP协议中用于断开连接的机制,确保数据传输的可靠性。由于TCP连接是全双工的,每个方向都必须单独进行关闭。

第一次挥手:主动方发送FIN报文

  • 当客户端决定关闭连接时,会向服务器发送一个FIN(结束)报文段,表明客户端不再发送数据

  • 在这个报文段中,FIN标志位被设置为1,序列号(seq)被设置为客户端当前的序列号x

  • 此时,客户端进入FIN_WAIT_1状态,等待服务器的确认

  • 需要注意的是,虽然客户端不再发送数据,但仍然可以接收服务器发送的数据

第二次挥手:被动方发送ACK确认

  • 服务器收到客户端的FIN报文段后,会向客户端发送一个ACK报文段,确认收到了客户端的关闭请求

  • 在这个报文段中,ACK标志位被设置为1,确认号(ack)被设置为客户端的序列号加1(即x+1)

  • 此时,服务器进入CLOSE_WAIT状态,客户端收到这个ACK报文段后,进入FIN_WAIT_2状态

  • 此时,客户端到服务器的连接已经关闭,但服务器到客户端的连接仍然开放,服务器可以继续向客户端发送数据

第三次挥手:被动方发送FIN报文

  • 当服务器也决定关闭连接时(可能是立即关闭,也可能是处理完剩余数据后关闭),会向客户端发送一个FIN报文段,表明服务器也不再发送数据

  • 在这个报文段中,FIN标志位被设置为1,序列号(seq)被设置为服务器当前的序列号y

  • 此时,服务器进入LAST_ACK状态,等待客户端的最终确认

第四次挥手:主动方发送最终ACK

  • 客户端收到服务器的FIN报文段后,会向服务器发送一个ACK报文段,确认收到了服务器的关闭请求

  • 在这个报文段中,ACK标志位被设置为1,确认号(ack)被设置为服务器的序列号加1(即y+1)

  • 此时,客户端进入TIME_WAIT状态,服务器收到这个ACK报文段后,进入CLOSED状态

  • 客户端在TIME_WAIT状态等待2MSL(Maximum Segment Lifetime,报文最大生存时间)时间后,才最终进入CLOSED状态

为什么是四次挥手?不是三次?

这是另一个常见的面试问题。四次挥手的设计是为了解决全双工通信中安全关闭连接的问题:

1. 全双工通信的特性 TCP连接是全双工的,即连接的两端都可以同时发送和接收数据。因此,关闭连接时,每个方向都需要单独关闭。第一次和第二次挥手关闭了客户端到服务器的连接,第三次和第四次挥手关闭了服务器到客户端的连接。

2. 数据传输的完整性 当客户端发送FIN报文段时,表示客户端不再发送数据,但服务器可能还有数据需要发送给客户端。服务器需要先确认客户端的FIN报文段(第二次挥手),然后继续发送剩余的数据,最后才能发送自己的FIN报文段(第三次挥手)。这样可以确保所有数据都被完整传输。

3. TIME_WAIT状态的重要性 客户端在发送最后一个ACK后进入TIME_WAIT状态,等待2MSL时间。这个设计有两个主要目的:

  • 确保最后一个ACK报文能够到达服务器。如果这个ACK报文丢失,服务器会重传FIN报文,客户端可以再次发送ACK

  • 防止"已失效的连接请求报文段"出现在新连接中。经过2MSL时间后,所有旧的报文都会从网络中消失

实际应用与最佳实践

在网络编程中的应用

理解TCP的三次握手和四次挥手机制对于开发高效、可靠的网络应用程序至关重要:

Socket编程中的连接管理

  • 服务器端:服务器通过socket()bind()listen()accept()函数来创建套接字、绑定地址、监听连接请求和接受连接。当客户端发起连接请求时,三次握手在accept()函数调用期间完成

  • 客户端:客户端通过socket()connect()函数来创建套接字和发起连接请求。三次握手在connect()函数调用期间完成

  • 连接释放:双方通过close()shutdown()函数来关闭连接,触发四次挥手过程

长连接与短连接的选择

  • 长连接:适用于频繁通信的场景,如数据库连接、消息队列等。可以减少连接建立和释放的开销

  • 短连接:适用于偶尔通信的场景,如简单的HTTP请求。可以避免长时间占用服务器资源

常见问题排查

连接建立失败

  • 检查服务器是否在监听指定端口

  • 检查防火墙设置是否阻止了连接

  • 使用tcpdumpwireshark抓包分析握手过程

连接异常断开

  • 检查网络是否稳定

  • 查看是否有超时设置不合理

  • 分析四次挥手过程是否完整

总结

TCP的三次握手和四次挥手机制是TCP协议可靠性的重要保障,它们确保了TCP连接的安全建立和释放。掌握这些原理不仅有助于我们更好地理解网络通信的本质,还能帮助我们在实际开发中设计出更加高效、可靠的网络应用。

三次握手通过精心设计的报文交换过程,解决了历史连接、序列号同步和资源浪费等问题;四次挥手则通过双向关闭机制,确保了全双工连接的优雅终止。理解这些机制,将使我们成为更好的网络工程师和开发者。

http://www.dtcms.com/a/390342.html

相关文章:

  • Python读取Excel中指定列的所有单元格内容
  • 【DMA】DMA入门:理解DMA与CPU的并行
  • Redis数据库(一)—— 初步理解Redis:从基础配置到持久化机制
  • Salesforce中的事件驱动架构:构建灵活可扩展的企业应用
  • OpenCV实现消除功能
  • Qt QValueAxis详解
  • deepseek大模型部署
  • 消息队列与定时器:如何优雅地处理耗时任务?
  • Maya绑定基础知识总结合集:父子关系和父子约束对比、目标约束示例
  • STM32开发(中断模式:外部中断)
  • (圆方树)洛谷 P4630 APIO2018 铁人两项 题解
  • windows10 使用moon-pilot并配置模型
  • Linux笔记---epoll用法及原理:从内核探究文件等待队列的本质-回调机制
  • Python快速入门专业版(三十三):函数参数陷阱:默认参数的“可变对象”问题(避坑指南)
  • Spring Security 框架 实践小项目(实现不同用户登录显示不同菜单以及每个菜单不同权限)
  • 开发避坑指南(49):Java Stream 对List中的字符串字段求和
  • 网络编程day02-组播,广播
  • 前端左侧菜单列表怎么写
  • LLM大模型和文心一言、豆包、deepseek对比
  • stm32h743iit6 配置 FMC 的时钟源
  • 中小企业数字化转型:从工具升级到思维转变
  • 数据传输中的三大难题,ETL 平台是如何解决的?
  • DAY16 字节流、字符流、IO资源的处理、Properties、ResourceBundle
  • 电气工程师面试题及答案
  • Halcon一维码与二维码识别技术解析
  • 【数据库系统Trip 第1站】总概
  • 关于 Python 编程语言常见问题及技术要点的说明
  • Mysql常用函数积累
  • AntV可视化(MCP 1.8)避坑指南
  • 学习日报|线程池 OOM