三次握手
step1:客户端连接请求过去,请求里面包含SYN标记和一个客户端的seq值,seq值是随机生成的。
step2:服务器收到请求后也会发一个对SYN包的确认包(SYN/ACK)回去,syn=1,ack=client_isn+1表示对第一个SYN包的确认,和一个服务器的seq值。
step3:客户端收到SYN/ACK 包,发一个确认包syn/ack,syn=0,ack的值为server_isn+1,通知A连接已建立。
四次挥手
【注意】中断连接端可以是Client端,也可以是Server端。
假设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连接就这样关闭了!
整个过程Client端所经历的状态如下:
而Server端所经历的过程如下:
【注意】
在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。
【问题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报文。