我们都知道tcp协议需要三次握手,那为什么不是两次握手呢,关于这个疑问我查了很多资料,看到很多的解释,现归纳总结如下,方便我们理解记忆
如果是两次握手,我们一起来看看下面两种场景
1.造成资源浪费
- Client向Server发送了一个a1的包
假如这时由于传输链路上遇到故障,导致a1传输到Server的时间特别长 假设1min
在这一分钟的时间内,由于Client没有收到Server对于a1包的确认,Client会以为上一个包发送丢了或者失败
那么Client会再发送一个a2的包
- Client又向Server发送了一个a2的包
这次Server正常收到
- 于是Server向Client发送了一个b2的确认包
- Client和Server建立链接
而随后滞后的a1包传到了Server,Server又会返回b1包确认
但是由于Client已经清除了a1包,所以Client会丢弃掉这个包,但是Server又会保持这个相当于“僵尸”的连接
这样就会造成白白浪费资源
在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段又突然传送到服务器,因为产生错误”
在另一部经典的《计算机网络》(AndrewS.Tanenbaum著,第四版)一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。
我们会发现这两种不同的表述其实阐明的是同一个问题。
2.死锁可能发生
- Client向Server发送了一个连接请求分组
- Server收到这个分组,并发送了确认应答分组
按照两次握手的协定,Server认为已经成功的建立连接,可以开始发送数据分组
而此时Server的应答分组传输丢失了,Client不知道Server是否已准备好,不知道Server建立什么样的序列号
Client甚至怀疑Server是否收到了自己的连接请求分组,在这种情况下,Client认为连接还未建立成功,将忽略Server发来的任何数据请求,只等待连接确认影带分组。而Server在发出的分组超时后,重复发送同样的分组,资源就形成了死锁。
而上面两种情况,如果使用三次握手就可以成功避免,三次握手完成的两个重要功能
- 既要双方做好发送数据的准备工作(双方都知道彼此已准备好)
- 允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认