TCP/IP协议三次握手和四次挥手

一、TCP/IP三次挥手
1、客户端请求连接,发送SYN包(同步序列编号),SYN =j。
2、服务器收到客户端SYN包并确认Ack = j+1,同时向客户端发送SYN包,SYN=k,客户端进入Established状态
3、客户端收到服务器发送的SYN包,发送Ack报文(Ack = k+1),服务器接收到后才进入Established状态

这时候有个问题,为什么是三次握手,不是两次握手或者四次握手?
我认为是这样的:如果假设是两次握手,客户端发送SYN包,服务器收到SYN包,并发送Ack报文。服务器会直接进入Established状态,开始分配资源,监听客户端要传过来的内容。
但是因为网络延迟或者阻塞,客户端发送消息的SYN还没到服务器,过了一段时间会有超时重传,它会重新发送SYN包,这时候假设服务器收到了第二个包的SYN,服务器开始分配资源了。如果又收到之前的SYN包,它也会分配资源,但是这个SYN是无效的连接,而一个进程打开的socket是有限度的, 维护这些死连接非常耗费资源。

还有一种解释是这样的,三次握手的好处在于能让双方都知道自己和对方的发送和接收都是OK的。分析如下:
在第一次握手过程中,服务端接收客户端的SYN,服务端是能知道自己的接收是好的,客户端的发送是好的。
在第二次握手过程中,客户端接收到了客户端的Ack报文,它能知道自己的发送和接收功能是好的。客户端的接收和发送都是好的。
这时候需要第三次握手,客户端发送Ack报文给服务端,让服务端确认服务端的发送是好的,客户端的接收是好的。

二、四次挥手:
1、客户端发送Fin,告诉服务端,自己传的已经传完了
2、服务端发送Ack,告诉客户端,我收到你的Fin请求了,但是我还没传完
3、服务端发送Fin,告诉客户端,我传完了,可以关闭了
4、客服端发送Ack报文,进入Time_Wait状态

为什么TIME_WAIT状态还需要等2MSL(报文最长存活时间)后才能返回到CLOSED状态?
这是因为虽然双方都同意关闭连接了,而且握手的4个报文也都协调和发送完毕,按理可以直接回到CLOSED状态(就好比从SYN_SEND状态到 ESTABLISH状态那样);但是因为我们必须要假想网络是不可靠的,你无法保证你最后发送的ACK报文会一定被对方收到,因此对方处于 LAST_ACK状态下的SOCKET可能会因为超时未收到ACK报文,而重发FIN报文,所以这个TIME_WAIT状态的作用就是用来重发可能丢失的 ACK报文

TCP/IP协议三次握手和四次挥手
此图来源于网络,百度图片,并不知道出处。