TCP 三次握手和四次挥手

本文详细解读TCP协议中的三次握手过程,包括客户端如何发起连接请求,服务器如何响应,以及如何通过三次交换确认连接。进一步探讨四次挥手断开连接的机制,解释FIN和ACK的作用,以及在实际应用中可能出现的RST包情况。同时讨论了TCP状态中的CLOSED_WAIT和TIME_WAIT状态,解释它们的意义和常见问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结一下这个基本知识点,确保自己真的理解正确了

先来看 TCP 状态图和 TCP 包格式

TCP 状态图

▲ TCP 状态图

TCP 包结构

▲ TCP 包结构

上面转自伯乐在线(伯乐在线转自 优快云 的一篇博文)的 TCP 包结构图其实存在错误。其中的 PST 应该为 RST,意为 Reset connection,后面介绍四次挥手的时候再介绍 RST。对于规范性的技术,最好是参考维基百科或 RFC 之类的文档。尽信书不如无书,我开始也没能发现

三次握手

TCP 三次握手

所谓 TCP 服务器端,是指其 TCP 协议栈会监听某个端口上的连接事件。

  1. 服务器开始处于监听状态。当客户端要连接服务器端时,客户端首先会发送一个 TCP 消息,其 SYN=1,并生成一个随机的 seq number,我们记为 seq=x。在用 Wireshark 分析 TCPDUMP 时,其显示的 seq 为 0,因为 Wireshark 为了用户方便,显示的是 seq 的相对值。在发送 SYN 之后,客户端的 TCP 栈便处于 SYN SENT 状态。
  2. 当服务器端收到客户端发来的 SYN 消息(SYN 位为 1 的 TCP 消息)之后,便回复了一个 TCP 消息,其 SYN=1,ACK=1,seq=y,ack=x+1。ACK 表示确认,ack 的值为其所确认的 SYN 包中 seq 值加 1。seq 值为一个随机值。因为 TCP 是一个双工的协议,两个方向都可以传输数据,所以需要在两个方向都确认可以传输数据,因此需要双方都发 SYN。这是服务器端的 TCP 协议栈对于当前连接来说处于 SYN RCVD 状态。
  3. 当客户端收到服务器端的 SYN,ACK 时,客户端便会返回一个 ACK 以确认这个 SYN 包,ack 便为 y+1。
  4. 当连接建立之后,对于 TCP 而言,就无所谓客户端服务器端

四次挥手

当 TCP 连接要被断开的时候,便会有所谓的四次挥手的过程。

四次挥手

  1. 用于断连接 TCP Flag 是 FIN。断连接时,一发起方放出一个 FIN 包,seq 值为一个随机值,这里记为 u。
  2. 对端在收到 FIN 之后会用 ACK 响应这个 FIN。所以 ack=u+1
  3. 接下来另一方也会发出 FIN 包。这还是因为 TCP 是双工的,所以双向都要关闭连接。在上图中,另一方发的 TCP 消息是 FIN + ACK。如果是演示四次挥手的过程,FIN 和 ACK 是分开的。在真实 TCP 协议栈的实现中,多数情况 FIN 和 ACK 是同时发出,即上图所演示的那样。如果另一端同时发送 FIN 和 ACK,那上图的第二个消息,即 ACK 消息其实是不存在的。所以,很多情况 TCP 断连接的过程是“三次挥手”。
  4. 同样,在客户端收到服务器端的 FIN+ACK 包之后,其也会回复一个 ACK 已确认之前的 FIN 包。

在断连接时,有时也能看到 RST 包。这种情况常见于在断连接开始之后,被动的一方还有数据没有发送完毕。这时这一方便会使用 RST 在断连接的同时发送剩余的数据。这些都是 TCP 协议栈(或者说是系统 Kerel)去根据不同情况作出的选择。

附:CLOSED_WAIT 和 TIME_WAIT

常见的和关闭连接相关的 TCP 状态有 TIME_WAIT 和 CLOSED_WAIT。如果常有大量的 TCP 短连接到 TCP 服务器上,那么就会看到很多的连接处于 TIME_WAIT 和 CLOSED_WAIT。

过多的 CLOSED_WAIT 或 TIME_WAIT 连接都是一件危险的事情。

过多的 CLOSED_WAIT

通常情况下 CLOSED_WAIT 状态持续的时间不应该很长。如果有连接长期处于 CLOSED_WAIT 往往以为着程序错误。曾经使用 Apache HttpComponents HttpClient,发现服务器端关闭 TCP 连接之后其不会自动关闭连接,必须手动执行连接关闭操作。如果不注意变化造成很多 CLOSED_WAIT 状态的连接(严格来说不应该说连接出于什么状态,而是 TCP 协议栈处于什么状态。用 netstat 查看的其实是本方协议栈的状态)。

过多的 TIME_WAIT

如上图所示,TIME_WAIT 状态在一段时间之后就会变为关闭状态。但是过多的 TIME_WAIT 也会消耗资源。一些系统设置可以降低大量 TIME_WAIT 对系统的影响。比如可以配置系统在连接数不够的时候重用 TIME_WAIT 连接。

vi /etc/sysctl.conf
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

转载于:https://my.oschina.net/lifany/blog/533598

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值