tcp为什么要三次握手,而不能二次握手? (经典话题见本质)

xumin330774233 2014-02-11 11:56:19
谢希仁版《计算机网络》中的例子是这样的,“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送ack包。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。

在谢希仁著《计算机网络》第四版中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。在另一部经典的《计算机网络》(Andrew S.Tanenbaum著,第四版)一书中讲“三次握手”的目的是为了解决“网络中存在延迟的重复分组”的问题。这两种不用的表述其实阐明的是同一个问题。

校评:为什么红线处说client不会理睬server的确认,不会向server发送数据,这个需要解释一下,我们知道客户端在调用connect函数之后进入了SYN_SEND状态,只有接收到服务器端的SYN+ACK包才进入ESTABLISHED状态。因为对于已经失效的连接请求报文,由于此时客户端没有进入SYN_SEND状态,而处于CLOSED状态,即使收到服务器端的SYN+ACK包,也不会产生任何状态变化,也就不会理踩server的确认和发送ack包了。


注意:上面的解释仅仅是假设客户端处于CLOSED状态时废弃包的到来,并没有对客户端处于非CLOSED状态时废弃包的到来进行分析,好歹通过google,得到了非CLOSED状态下为什么两次握手可能会出现的问题,这里也分两种情况,一种是废弃的报文的干扰,一种是废弃的SYN报文的干扰。





附华中科技大学有一题研究生入学考题,是下面题目的中文翻译版(不过我觉得这个答案有点牵强,毕竟现在tcp传输机制中都有定时器,会有超时重传,不会导致死锁的,当然如果没有超时机制,死锁还是可能的):

Imagine that a two-way handshake rather than a three-way handshake were used to set up connections. In other words, the third message was not required. Are deadlocks now possible? Give an example or show that none exist.

Answer:
Deadlocks are possible. For example, a packet arrives at A out of the blue, and A acknowledges it. The acknowledgement gets lost, but A is now open while B knows nothing at all about what has happened. Now the same thing happens to B, and both are open, but expecting different sequence numbers. Timeouts have to be introduced to avoid the deadlocks.


网上有一段流传很广的解释:

为什么不能用两次握手进行连接?

我们知道,3次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,C在S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分 组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。


校评:这个解释也值得商榷,这里指说S超时重传,难道C没有收到S的ACK信号,不会重新发送SYN信号么? 只要重新发送SYN,S端自然也会发送确认应答分组,这样就不会导致死锁。



http://blog.csdn.net/xumin330774233/article/details/14448715
...全文
920 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
SUNWESTRONG 2014-02-13
  • 打赏
  • 举报
回复
有才,精辟,学习了。
ljc007 2014-02-12
  • 打赏
  • 举报
回复
感谢分享
iasky 2014-02-12
  • 打赏
  • 举报
回复
mark,不错。

4,436

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 内核源代码研究区
社区管理员
  • 内核源代码研究区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧