网络TCP建立连接为什么需要三次握手而结束要四次

本文通过形象的对话形式,解释了TCP协议中三次握手建立连接和四次挥手终止连接的过程,并详细解析了为何需要四次挥手及客户端等待2MSL的原因。

 举个打电话的例子:

  A : 你好我是A,你听得到我在说话吗

  B : 听到了,我是B,你听到我在说话吗

  A : 嗯,听到了

  建立连接,开始聊天!

这里写图片描述

这里写图片描述

为什么TCP协议终止链接要四次?

1、当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据口(当然确认信号还是可以发),就会发FIN给主机B。

2、主机B收到A发送的FIN,表示收到了,就会发送ACK回复。

3、但这是B可能还在发送数据,没有想要关闭数据口的意思,所以FIN与ACK不是同时发送的,而是等到B数据发送完了,才会发送FIN给主机A。

4、A收到B发来的FIN,知道B的数据也发送完了,回复ACK, A等待2MSL以后,没有收到B传来的任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接了。

A为什么等待2MSL,从TIME_WAIT到CLOSE?

在Client发送出最后的ACK回复,但该ACK可能丢失。Server如果没有收到ACK,将不断重复发送FIN片段。所以Client不能立即关闭,它必须确认Server接收到了该ACK。Client会在发送出ACK之后进入到TIME_WAIT状态。Client会设置一个计时器,等待2MSL的时间。如果在该时间内再次收到FIN,那么Client会重发ACK并再次等待2MSL。所谓的2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果直到2MSL,Client都没有再次收到FIN,那么Client推断ACK已经被成功接收,则结束TCP连接。

这个网上转载的例子不错:

三次握手:
A:“喂,你听得到吗?”A->SYN_SEND

B:“我听得到呀,你听得到我吗?”应答与请求同时发出 B->SYN_RCVD | A->ESTABLISHED

A:“我能听到你,今天balabala……”B->ESTABLISHED

四次挥手:
A:“喂,我不说了。”A->FIN_WAIT1

B:“我知道了。等下,上一句还没说完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,说完了,我也不说了。”B->LAST_ACK

A:”我知道了。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保证B收到了消息,否则重说一次”我知道了”,A->CLOSED

链接:https://zhuanlan.zhihu.com/p/21940234

### TCP建立连接采用三次握手的原因 TCP建立连接采用三次握手主要有两个重要原因。一是为了防止已失效的连接请求报文段突然又传到服务端,因而产生错误。假定出现一种异常情况,即客户端发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,一直延迟到连接释放以后的某个时间才到达服务端,本来这是一个早已失效的报文段。但服务端收到此失效的连接请求报文段后,就误认为是客户端又发出一次新的连接请求,于是就向客户端发出确认报文段,同意建立连接。假定不采用三次握手,那么只要服务端发出确认,新的连接建立了,这样服务端一直等待客户端发来数据,服务端的许多资源就这样白白浪费了,可能还会产生死锁问题,采用三次握手恰好就避免了这个问题 [^3]。 二是为了同步客户端和服务端的初始序列号以及确认双方的发送和接收能力。客户端向服务端发送连接请求报文段,包含自己的初始序列号,服务端收到后发送确认报文段,包含自己的初始序列号和对客户端序列号的确认,客户端再发送确认报文段,完成序列号的同步。通过三次握手,双方都能明确对方的序列号和接收能力,确保后续数据传输的正确性 [^1][^2][^3][^4]。 ### TCP断开连接采用四次挥手的原因 TCP断开连接采用四次挥手是因为TCP是全双工通信,即双方都可以独立地发送和接收数据。当一方想要关闭连接时,它会发送一个FIN报文段,表示自己已经没有数据要发送了,但仍然可以接收对方的数据。另一方收到FIN报文段后,会发送一个ACK报文段进行确认。此时,发送FIN的一方不能再发送数据,但可以接收数据。之后,另一方也可能有数据要发送,当它发送完所有数据后,会发送一个FIN报文段,表示自己也没有数据要发送了,对方收到后再发送一个ACK报文段进行确认,至此连接完全关闭。由于每个方向的关闭都需要一个FIN和一个ACK,所以总共需要四次挥手 [^1]。 ```python # 简单模拟TCP三次握手四次挥手的过程 # 三次握手 print("客户端向服务端发送SYN包,请求建立连接") print("服务端收到SYN包,向客户端发送SYN+ACK包,表示同意建立连接") print("客户端收到SYN+ACK包,向服务端发送ACK包,连接建立成功") # 四次挥手 print("客户端向服务端发送FIN包,表示请求关闭连接") print("服务端收到FIN包,向客户端发送ACK包,表示同意关闭客户端到服务端的连接") print("服务端向客户端发送FIN包,表示请求关闭服务端到客户端的连接") print("客户端收到FIN包,向服务端发送ACK包,表示同意关闭服务端到客户端的连接连接关闭完成") ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值