三次握手
如图所示
首先,客户端处于Closed状态,服务端处于Listen状态。
- 客户端发送SYN=1,意思是我客户端要请求建立联机了。 seq=x为 seq number=12345随机产生的数据包。此时,客户端状态从Closed 变成SYN_SEND
- 服务端 ACK 意思是,我服务端收到了,SYN=1,向你发送,我也要联机了,seq = y 同上,也是自己产生的随机数据包,ack=x+1 为在上一次发送过来的seq加一,发送回去,此时,服务端的状态从LISTEN变成SYN_RCVD。
- 客户端ACK =1 ,收到服务端发过来的请求了,seq=x+1,ack=y+1,验证一下。状态变为ESTAblish。
四次挥手
- 客户端establish状态,向服务端发送一个FIN状态码,我准备断开连接了。seq=u,发送一个随机数据包。状态进入FIN_wait
- 服务端establish状态,向客户端发送ACK=1,确认收到,seq=v 发送自己的数据包,ack=u+1,验证成功,状态变成CLOSED_WAIT。
- 客户端FIN_WAIT状态,向客户端发送FIN=1,我也要断开连接了,ACK=1,确认ACK,当为1时,才有效。seq=w,随机数据包。 ack=u+1,同第二次。服务端状态变为LAST_ACK。
- 在客户端等待2MS后,向服务端发送ACK=1,收到,seq=u+1,ack=w+1。状态变成CLOSED。
此时,有几个问题:
1.1 为什么需要三次握手,两次不行吗?
第一次握手:客户端发送网络包,服务端收到了
这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
第二次握手:服务端发包,客户端收到了。
这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端发包,服务端收到了。
这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。
1.2 为什么要等2MSL
1.确保客户端发送的最后一个ACK报文段能够到达服务器,因为这个ACK可能会丢失,从而导致处在LAST_ACK状态的服务器收不到对FIN_ACK的确认报文。服务器会超时重传这个FIN_ACK。接着客户端再重传一次确认,重新启动时间等待计时器。最后客户端和服务器都能正常关闭,如果不等2MSL,而是在发送完ACK之后直接释放关闭,一旦这个ACK丢失,服务器就无法正常进入关闭连接状态。
2.防止失效的报文段。客户端在发送最后一个ACK之后,再经过2MSL,就可以使本链接持续时间内所产生的所有报文段都从网络中消失。从而保证在关闭连接后不会还有在网络中滞留的报文段去骚扰服务器。