
今天和大家先分享一篇关于TCP协议及三次握手的知识。
TCP协议相关文章回顾↓
网络基础知识夯实总结(三):TCP协议
工业以太网基础知识之数据包、IP包、TCP/UDP 包结构
一、三次握手
三次握手:在通信之前,会先通过三次握手的机制来确认两端口之间的连接是否可用。而UDP不需要确认是否可用,直接传。
三次握手机制

一开始客户端和服务端都是关闭状态,但是在某个时刻,客户端需要和服务端进行通信,此时双方都会各自准备好端口,服务器段的端口会处于监听状态,等待客户端的连接。
客户端可会知道自己的端口号,和目的进程的端口号,这样才能发起请求。
第一次握手:客户端想与服务器进行连接了,所以状态变为主动打开,同时发送一个连接请求报文给服务器段SYN=1,并且会携带x个字节过去。
发送完请求连接报文后,客户端的状态就变为了SYN_SENT,可以说这个状态是等待发送确认(为了发送第三次握手时的确认包)
第二次握手:服务端接收到连接请求报文后,从LSTTEN状态变为被动打开状态,然后给客户端返回一个报文。这个报文有两层意思,一是确认报文,而可以达到告诉客户端,我也打开连接了。
发完后,变为SYN_RCVD状态(也可以说是等待接受确认状态,接受客户端发过来的确认包)
第三次握手:客户端得到服务器端的确认和知道服务器端也已经准备好了连接后,还会发一个确认报文到服务器端,告诉服务器端,我接到了你发送的报文,接下来就让我们两个进行连接了。
客户端发送完确认报文后,进入ESTABLISHED,而服务器接到了,也变为ESTABLISHED
进入到ESTABLISHED状态后,连接就已经完成了,可以进行通信了。
问题:为什么需要第三次握手,有前面两次不就已经可以了吗?
假设没有第三次握手,客户端发送一个连接请求报文过去,但是因为网络延迟,在等待了一个超时时间后,客户端就会再重新发一个请求连接报文过去,然后正常的进行;
服务器端发回一个确认连接报文,然后就开始通讯,通讯结束后,那个第一次因为网络延迟的请求连接报文到了服务器端,服务器端不知道这个报文已经失效,也发回了一个确认连接报文。
客户端接收后,发现自己并没有发送连接请求(因为超时了,所以就认为自己没有发),所以对这个确认连接请求就什么也不做,但是此时客户端不这么认为,他认为连接已经建立了,就一直打开着等待客户端传数据过来,这就造成了极大的浪费。
如果有了第三次握手,那么客户端就可以通知服务器了,所以第三次握手也很重要!
二、四次挥手
四次挥手是用来断开服务器和客户端之间的通信的,之所以要断开连接,是因为TCP/IP 协议是要占用端口号的,而计算机的端口却是有限的,不进行断开的话,势必会造成计算机资源的浪费。
1、在整个通信的过程中,谁先发起请求,谁就是客户端。
当客户端的数据传输到尾部时,客户端向服务器发送带有FIN标志的数据包,使其明白自己准备断开通信了。
2、因为TCP的通信是使用全双工通信的WebSocket,所以在断开连接的时候也应该是双向的;当服务器收到带有FIN标志的数据包时,其必不会直接发送FIN标志断开通信的请求,而是先发送一个带有ACK标志的应答信息,使客户端明白服务器还有数据要进行发送。
3、当 服务器的数据发送完成后,向客户端发送带有FIN标志的数据包,通知客户端断开连接。
4、这一次挥手是我觉得四次挥手中设计的最巧妙的一次。
当客户端收到FIN后,担心网络上某些不可控制的因素导致服务器不知道他要断开连接,会发送ACK进行确认,同时把自己设置成TIME_WAIT状态并启动定时器,**在TCP的定时器到达后客户端并没有接收到请求,会重新发送;当服务器收到请求后就断开连接;当客户端等待2MLS(两倍报文最大生存时间)后,没有收到请求重传的请求后,客户端这边就断开连接,**整个TCP通信就结束了。
四次挥手的图如下所示:

问题:关闭的时候为什么会是四次挥手?
四次挥手不能像三次握手一样,三次握手可以将ACK+SYN 一起发送,ACK用于确认信息,SYN却是用来建立联机的;
四次挥手中ACK是不能和FIN一起发送,ACK只是告诉客户端确认我收到了,等我将数据发送完毕之后会向其发送FIN的标志,所以四次挥手是不能够改变的。
