Python3 &TCP三次握手和四次挥手通俗理解

TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓的“连接”,其实是客户端和服务端保存的一份关于对方的信息,如ip地址、端口号等。

TCP可以看成是一种字节流,它会处理IP层或以下的层的丢包、重复以及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。

一个TCP连接由一个4元组构成,分别是两个IP地址和两个端口号。一个TCP连接通常分为三个阶段:连接、数据传输、退出(关闭)。通过三次握手建立一个链接,通过四次挥手来关闭一个连接。

三次握手过程

建立TCP连接时,需要客户端和服务器共发送3个包。

第一次:客户端发送初始序号seq=x和syn=1请求标志
第二次:服务器发送请求标志syn,发送确认标志ACK,发送自己的序号seq=y,发送客户端的确认序号ack=x+1
第三次:客户端发送ACK确认号,发送自己的序号seq=x+1,发送对方的确认号ack=y+1


image.png

简单来说就是:
1)发送方:hi,小明,听得到吗?
2)接收方:听得到,你能听到我说话吗?
3)发送方:听到了,我们的通信可以开始了。
上面分析过程可以看出,握手两次达不到让双方都得出自己、对方的接收、发送能力都正常的结论的。

四次挥手过程

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发。
由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。

第1次挥手:Client发送一个FIN=1, 序列号seq=u,用来关闭Client到Server的数据传送,进入FIN-WAIT-1状态。这表示Client没有数据要发送给Server了。
第2次挥手:Server收到Client发送的FIN后,发送一个确认标志ACK=1,Client的确认号ack=u+1,自己Server的序列号seq=v给Client,Server进入CLOSE_WAIT状态(Client向Server的方向就释放了,这时候处于半关闭状态,即Client已经没有数据要发送了,但是Server若发送数据,Client依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间)。
第3次挥手:Client收到Server确认结果后,进入FIN-WAIT-2状态(等待Server发送连接释放报文,即在这之前还需要接受Server发送的最后的数据)。此时Server将最后的数据发送完毕后,就向Client发送连接释放报文,Server发送释放FIN=1信号,确认标志ACK=1,确认序号ack=u+1,自己Server的序号seq=w,用来关闭Server到Client的数据传送。Server进入LAST-ACK(最后确认态),等待Client的确认。
第4次挥手:Client收到Server的连接释放报文后,必须发出确认,ACK=1,ack=w+1,自己的seq=u+1,Client 进入TIME-WAIT(时间等待)。Server收到了Client发出的确认,立即进入CLOSED状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间,则Client 端进入CLOSE状态,完成四次挥手。

image.png

简单来说就是:
1)Client: 小明,我的话都说完了
2)Server:好的,我都听到了,不过,我还没说完,等一下
3)Server:好了,我也说完了
4)Client: 好的,那我们这次的通话结束

【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到Server端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送。故需要四步握手。

【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:按道理,四个报文都发送完毕,就可以直接进入CLOSE状态了,假如网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。在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连接。

你可能感兴趣的:(Python3 &TCP三次握手和四次挥手通俗理解)