python之网络编程TCP四次挥手

TCP四次挥手

什么是TCP的四次挥手呢?
当TCP连接过程中有一方需要断开连接的时候,这一过程在客户端和服务器开始关闭到关闭成功的过程中发送的四个数据包,我们称为四次挥手,其中主动发起停止的一方需要等待2MSL时间
让我们来看一下TCP四次挥手的流程图
python之网络编程TCP四次挥手第⼀次挥⼿:主机1(可以是客户端,也可以是服务器端),设置 Sequence Number(序号seq) 和 Acknowledgment Number(确认号,ack) ,向主机2发送⼀个 FIN 报⽂段;此时,主机1进 ⼊ FIN_WAIT_1 状态;这表示主机1没有数据要发送给主机2了;

第⼆次挥⼿:主机2收到了主机1发送的 FIN 报⽂段,向主机1回⼀个 ACK 报⽂段, Acknowledgment Number 为 Sequence Number 加1;主机1进⼊ FIN_WAIT_2 状态;主机2告诉主机1,我也没有数据要 发送了,可以进⾏关闭连接了;

第三次挥⼿:主机2向主机1发送 FIN 报⽂段,请求关闭连接,同时主机2进⼊ CLOSE_WAIT 状态;

第四次挥⼿:主机1收到主机2发送的 FIN 报⽂段,向主机2发送 ACK 报⽂段,然后主机1进 ⼊ TIME_WAIT 状态;主机2收到主机1的 ACK 报⽂段以后,就关闭连接;此时,主机1等待2MSL后依 然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

MSL:最⼤报⽂⽣存时间,基本上为30s到2分钟

有时候服务器主动断开,四次挥手的最后一次由于需要等待2MSL时间,所以断开连接时候可能造成地址端口被使用的情况,这是由于断开tcp服务需要等待2MSL时间在socket SO_REUSEADDR 参数里可以创建地址重用,不需要等待2MSL时间。

问题

1.为什么TIME_WAIT状态需要经过2MSL(最⼤报⽂段⽣存时间)才能返回到CLOSE状态? ⾸先,MSL即Maximum Segment Lifetime,就是最⼤报⽂⽣存时间,是任何报⽂在⽹络上 的存在的最长时间,超过这个时间报⽂将被丢弃。《TCP/IP详解》中是这样描述的:MSL是任何 报⽂段被丢弃前在⽹络内的最⻓时间。RFC 793中规定MSL为2分钟,实际应⽤中常⽤的是30 秒、1分钟、2分钟等。 TCP的TIME_WAIT需要等待2MSL,当TCP的⼀端发起主动关闭,三次挥⼿完成后发送第四 次挥⼿的ACK包后就进⼊这个状态,等待2MSL时间主要⽬的是:防⽌最后⼀个ACK包对⽅没有 收到,那么对⽅在超时后将重发第三次握⼿的FIN包,主动关闭端接到重发的FIN包后可以再发⼀ 个ACK应答包。在TIME_WAIT状态时两端的端⼝不能使⽤,要等到2MSL时间结束才可以继续使 ⽤。当连接处于2MSL等待阶段时任何迟到的报⽂段都将被丢弃。

2.client发送完最后⼀个ack之后,进⼊time_wait状态,但是他怎么知道server有没有收到这个ack呢? 莫⾮sever也要等待⼀段时间,如果收到了这个ack就close,如果没有收到就再发⼀个fin给client?这么 说server最后也有⼀个time_wait哦?求解答! 因为⽹络原因,主动关闭的⼀⽅发送的这个ACK包很可能延迟,从⽽触发被动连接⼀⽅重传 FIN包。极端情况下,这⼀去⼀回,就是两倍的MSL时⻓。如果主动关闭的⼀⽅跳过TIME_WAIT 直接进⼊CLOSED,或者在TIME_WAIT停留的时⻓不⾜两倍的MSL,那么当被动关闭的⼀⽅早 python⾼级 tcp的4次挥⼿
先发出的延迟包到达后,就可能出现类似下⾯的问题:1.旧的TCP连接已经不存在了,系统此时 只能返回RST包2.新的TCP连接被建⽴起来了,延迟包可能⼲扰新的连接,这就是为什么 time_wait需要等待2MSL时长的原因。

3.为什么连接的时候是三次握⼿,关闭的时候却是四次握⼿? 因为当Server端收到Client端的SYN连接请求报⽂后,可以直接发送SYN+ACK报⽂。其中 ACK报⽂是⽤来应答的,SYN报⽂是⽤来同步的。但是关闭连接时,当Server端收到FIN报⽂ 时,很可能并不会⽴即关闭SOCKET,所以只能先回复⼀个ACK报⽂,告诉Client端,“你发的 FIN报⽂我收到了”。只有等到我Server端所有的报⽂都发送完了,我才能发送FIN报⽂,因此不 能⼀起发送。故需要四步握⼿。

本文由学习视频总结笔记,加深理解过程,不足之处还请谅解。