为什么必须是三次握手?
大家都知道传输层(点击这里去传输层)中的TCP协议是面向连接的,提供可靠的连接服务,其中最出名的就是三次握手和四次挥手,今天先讲解三次握手(四次挥手点这里),如下图
喜欢钻牛角尖的我在学习三次握手的时候就想到了几个问题:为什么三次握手是三次?不是一次、两次或者更多?如果是两次或者是一次会出现什么情况?带着这个问题我找了好多资料,发现了其中的奥秘。
一次握手的情况:
由于TCP是面向连接的,一次很明显时不可能的,因为客户端发出连接消息后,却没有接收到来自服务端的回应,客户端就无法确定服务端接是否收到了连接请求,当然也就不能确定是否连接成功。
两次握手的情况:
既然一次客户端接收不到服务端的回应,那就连接两次,接收到回应就说明服务端接收到了连接请求,可以连理连接了。结果并不是这样。
如果客户端想建立连接,给服务端发了一个连接请求(SYN),但是由于网络中种种情况,导致没有及时到达服务端,这就导致客户端在很长一段时间中没有收到回复消息(ACK),这时客户端又给服务端发送一个SYN,这次的发送和接收的很顺利,很快就收到了ACK,但是这时之前的SYN终于到了服务端,服务端规规矩矩的为这个SYN申请资源,然后返回ACK。由于之前的SYN已经失效了,所以客户端也不会去理会这个ACK,但是傻乎乎的服务端并不知道这个SYN已经失效了,一直为他委会着资源,这就造成了资源的浪费。
三次握手的情况:
一发一收的两次握手既然不行,那么三次握手就可以了吗?接着往下看。
在两次握手中服务端不知道当前这个SYN是不是有效的,三次握手就很好的解决了这个问题,第三次握手就是客户端给服务端回复第二次握手,这也就是说服务端会等第三次握手的到来,如果第三次握手迟迟不来,服务端就可以识别这个SYN是无效的,就会将他的资源释放了。还有一种情况就是第三次握手由于网络中的种种原因失败了,这时候客户端认为自己已经连接好了,就会给服务端发送数据,服务端由于没有收到第三次握手,就会以RST包对客户端响应,收到RST的的客户端就知道第三次握手没有成功,就会重新连接。在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。
四次握手和两次握手的情况一样,五次握手和三次握手的情况一样,以此类推,奇数次握手的情况与三次握手相同,同理偶数次握手与两次握手一样,所以为了更快的连接,就使用三次握手最合适。
每次握手失败对应的措施:
第一次握手失败:
如果第一次的SYN传输失败,两端都不会申请资源。如果一段时间后之前的SYN发送成功了,这时客户端只会接收他最后发送的SYN的SYN+ACK回应,其他的一概忽略,服务端也是如此,会将之前多申请的资源释放了。
第二次握手失败:
如果服务端发送的SYN+ACK传输失败,客户端由于没有收到这条响应,不会申请资源,虽然服务端申请了资源,但是迟迟收不到来自客户端的ACK,也会将该资源释放。
第三次握手失败:
如果第三次握手的ACK传输失败,导致服务端迟迟没有收到ACK,就会释放资源,这时候客户端认为自己已经连接好了,就会给服务端发送数据,服务端由于没有收到第三次握手,就会以RST包对客户端响应。但是实际上服务端会因为没有收到客户端的ACK多次发送SYN+ACK,次数是可以设置的,如果最后还是没有收到客户端的ACK,则释放资源。
这是我自己理解,有什么不合适的地方,欢迎各位大佬批评指正。