三次握手
在进行网络通信之前,套接字Socket之间的连接可以分为四个步骤:服务器监听,客户端请求服务,服务器确认,客户端确认,进行通信。
而这些确认的步骤就需要使用“三次握手”来完成,三次握手的本来目的其实就是为了确认几种能力即:服务器端和客户端分别验证需要通信的服务器和客户端发包及收包的能力,而确认这些信息至少需要三次的数据交换即“三次握手”。
客户端 | 服务端 | |||||||
自己发包 | 自己收包 | 对方发包 | 对方收包 | 自己发包 | 自己收包 | 对方发包 | 对方收包 | |
第一次握手 | N | N | N | N | N | Y | Y | N |
第二次握手 | Y | Y | Y | Y | N | Y | Y | N |
第三次握手 | Y | Y | Y | Y | Y | Y | Y | Y |
实际操作过程就如上图所示:
- 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
- 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
- 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
完成了三次握手,服务器与客户端都无故障地增收或发送了相应有数据包,之后就可以进行通信啦!
四次挥手
客户端与服务器通信结束之后,需要断开连接以释放资源。四次挥手的本质目的也是服务器端和客户端分别确认对方和自己都不再发送和接收数据包了,而确认这个过程需要进行四次交流,因此称为“四次挥手”。
客户端 | 服务端 | |||||||
自己不发 | 自己不收 | 对方不发 | 对方不收 | 自己不发 | 自己不收 | 对方不发 | 对方不收 | |
第一次挥手 | N | N | N | N | N | Y | Y | N |
第二次挥手 | Y | N | N | Y | N | Y | Y | N |
第三次挥手 | Y | Y | Y | Y | N | Y | Y | N |
第四次挥手 | Y | Y | Y | Y | Y | Y | Y | Y |
之所以要进行四次挥手,而不能直接断开,就是防止服务器或者客户端还有未发送或未接收完的数据,因此客户端在提出不再发包请求并收到应答之后,会有一断时间进入等待,这个过程是就是看看服务器还有没有未发完的数据,有的话,快点发完。
引用白话文解释:假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,“告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,“告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,“就知道可以断开连接了”。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!