Linux三次握手和四次挥手

本文详细解析了TCP协议的三次握手和四次挥手的过程及其原因。解释了为何需要三次握手而非两次或四次,以及四次挥手背后的原理。并介绍了在TCP连接建立与断开时的状态变迁。

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

tcp协议格式

tcp三次握手过程
1.client端向server端发送一个SYN(连接请求)的报文,其中包含了一个初始序列号和一个窗口大小(主要是为了告诉对方自己的接受能力是多大);
2.服务器收到客户端发送的SYN报文后,也同样向对方发送一个SYN,ACK的报文,还有一个窗口大小(表示服务器上用来存储来自客户端数据多少的一个能力);
3,客户端收到服务器端返回的SYN和ACK之后,向服务器发送一个确认号+1和序列号+1的ACK报文。
如图所示:

注意:
在三次握手建立连接时,除了要建立连接以外,还要处理一些通信细节,其中包括了最大段尺寸(MMS)和滑动窗口(WIN)
为什么要三次握手?
在谢希仁的《计算机网络》一书中是这样讲的。“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。
总结:
三次握手的目的是为了确保通信的建立,如果采用两次握手,client发送请求之后,server端同意之后就会认为通信已经建立好了,开始发送数据,但是如果确认报文在通信过程中丢失了,那么client端认为通信没有建立成功,那么就会忽略server,但是server在发送报文超时之后,又会进行超时重传,进而造成死锁。
为什么不采用四次握手建立通信?
在上图中我们会发现在第三次握手的时候有可能失败,在第三次握手之后,客户端就会认为通信建立好了,但是服务器端有可能会收不到确认报文,导致通信失败,但是这影响不大,因为这只影响了一个client端,相对于两次握手,如果失败影响的是所有的client,三次握手就可以解决问题,四次握手显得多余了。
为什么要四次挥手?
四次挥手过程详解图

由于tcp建立连接是全双工的,因此在请求断开连接时必须双方都要同意,这就像我们现实生活中的离婚一样,必须征求双方的同意。
当A给B说:我们离婚吧!
B说:好!
B说:我们离婚吧!
A说:行!

FIN_WAIT_1:FIN_WAIT_1状态实际上是当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文,此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方何种情况下,都应该马 上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。
  FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。
  TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
  CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的 ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却也收到了对方的FIN报文。什 么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报 文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。
  CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对 方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以 close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT状态下,需要完成的事情是等待你去关闭连接。
  LAST_ACK: 这个状态还是比较容易好理解的,它是被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。
为什么主动断开连接的一方会进入TIME_WAIT?
TIME_WAIT含义: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
MSL是最长报文长度,在RFC793建议设为2分钟,2MSL就是4分钟。
这里,为什么A要等待这个时间之后才能断开连接呢?
1、为了保证客户端发送的最后一个ACK报文段能够到达服务器。因为这个ACK有可能丢失,从而导致处在LAST-ACK状态的服务器收不到对FIN-ACK的确认报文。服务器会超时重传这个FIN-ACK,接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常的关闭。假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。

2、他还可以防止已失效的报文段。客户端在发送最后一个ACK之后,再经过经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从保证在关闭连接后不会有还在网络中滞留的报文段去骚扰服务器。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值