为什么 TCP 是3次握手4次挥手?
① 为什么是三次握手?(A: 客户端,B: 服务器)
TCP连接是全双工的,意味着数据在两个方向上可以同时传输。因此,建立连接的关键是确保双方都具有发送和接收的能力,并且要同步双方的初始序列号(Sequence Number, SN),这是TCP可靠性传输的基石。
- 第一次握手 (SYN):客户端发送一个SYN包(SYN=1)到服务器,并选择一个初始序列号 seq = x。这表示:“你好服务器,我想建立连接。我的初始序列号是x。”
意义:客户端证明了自己有发送能力。
- 第二次握手 (SYN-ACK):服务器收到SYN包后,必须进行确认。它发送一个SYN-ACK包(SYN=1, ACK=1),确认号为 ack = x + 1,同时自己也选择一个初始序列号 seq = y。这表示:“收到你的请求了(x),我同意建立连接。我的初始序列号是y。”
意义:服务器证明了自己有接收能力和发送能力。
- 第三次握手 (ACK):客户端收到服务器的SYN-ACK包后,再次发送一个ACK包(ACK=1),确认号为 ack = y + 1,序列号为 seq = x + 1。这表示:“收到你的同意了(y),连接已建立,我们可以开始发送数据了。”
意义:客户端证明了自己有接收能力。
② 为什么是四次挥手?(A: 主动关闭方,B: 被动关闭方)
TCP连接是全双工的,这意味着数据在两个方向上独立传输。因此,关闭连接需要分别关闭这两个方向的数据流。
- 第一次挥手 (FIN):主动关闭方(比如客户端)发送一个FIN包(FIN=1),序列号为 seq = u。这表示:“我这边没有数据要发送了,准备关闭连接。”(即关闭客户端到服务器的数据通道)
意义:主动方通知对方,我发完了。
- 第二次挥手 (ACK):被动关闭方(服务器)收到FIN后,发送一个ACK包(ACK=1),确认号为 ack = u + 1。这表示:“知道你发完了。”
意义:被动方确认收到了主动方的关闭请求。此时,从主动方到被动方这个方向的连接就关闭了。但服务器可能还有数据没发完。
- 第三次挥手 (FIN):当被动方也准备好了关闭连接时(数据处理完了),它发送一个FIN包(FIN=1),序列号为 seq = w。这表示:“我这边也发完了,我也要关闭了。”(即关闭服务器到客户端的数据通道)
意义:被动方发起自己方向的关闭请求。
- 第四次挥手 (ACK):主动关闭方收到FIN后,发送一个ACK包(ACK=1),确认号为 ack = w + 1。这表示:“知道你也要关了,再见。”
意义:主动方确认被动方的关闭请求。此时,整个TCP连接才正式关闭。
③ 可以将第二次挥手的ACK和第三次挥手的FIN合并成一个包发送吗?
可以,但前提是对方没有数据要发送了。在很多情况下,服务器收到FIN时可能正在发送数据,所以ACK先发出去,等所有数据发完再发FIN,这就自然形成了四次挥手。Linux内核中有一个选项 tcp_fin_timeout 来控制这个行为。
④ tcp_fin_timeout 作用是?
TCP 四次挥手中主动关闭方的状态变化:
- 主动关闭方(如 Client)发送 FIN 包,进入 FIN-WAIT-1 状态。
- 收到对端(如 Server)回应的 ACK 包后,进入 FIN-WAIT-2 状态。此时,tcp_fin_timeout 计时器开始生效。
- 在 FIN-WAIT-2 状态,主动关闭方等待对端发送它自己的 FIN 包(即第三次挥手)。
- 有两种可能的结果:
正常情况:在 tcp_fin_timeout 超时之前,收到了对端的 FIN 包。主动关闭方回复 ACK(第四次挥手),然后连接直接进入 TIME-WAIT 状态,FIN-WAIT-2 状态结束。
异常情况:对端因为某种原因(如程序崩溃、进程被杀、网络丢包等)始终没有发送 FIN 包。此时,tcp_fin_timeout 计时器到期,内核会强制将这条处于 FIN-WAIT-2 状态的连接关闭,释放相关资源(如内存、端口等)。
为什么要设置这个超时?
如果没有这个超时限制,而对端又永远不发送 FIN 包,那么主动关闭方的连接就会永远停留在 FIN-WAIT-2 状态。每一个这样的连接都会占用系统的内存和一个文件描述符。如果大量连接出现这种情况,就会耗尽系统资源,导致新的连接无法建立,形成一种拒绝服务(DoS)状态。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/910839.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!