TCP建连时为什么是3次握手,而不是2次或4次?

在发表最近博客的时候,我的小舅考了我一个问题:为什么是3次握手,而不是1次、2次或4次?

我从来没有想过这个问题,总以为是学习计算机就是学习一系列定好的规则。仔细想想,仔细想想,任何事物的方法都是有一定的原因的。就像那句话说的 “这世上没有无缘无故的爱”一样,TCP采取3次握手一定有它的道理!

tcp建立连接时是3次握手,断开连接时是4次握手。这是大家都知道的事,但是为什么要这样设定呢?

先引入一个简单的解答:

简单说,让双方都证实对方能发收。
知道对方能收是因为收到对方的因为收到而发的回应。
具体:
1:A发,B收, B知道A能发
2:B发,A收, A知道B能发收
3:A发,B收, B知道A能收

如果从通信的可靠性出发,这个世上好像不存在100%可靠的协议,在知乎上有一个例子是这样的:

这是个经典的“两军通信”问题,假设场景是这样的:
在山的两头是红军1和红军2,山上是蓝军,红军1和2都不是蓝军的对手,想打败蓝军只有一起动手。那么红军1和2如何通信才能确定双方在同一个时间动手呢?

红军1的传令军成功偷偷越过大山告诉红军2,明天早上中午十二点一起动手;
红军2表示赞同,但是红军1并不确定红军2是否收到了消息,贸然动手必定失败,所以红军2的传令军越过大山告诉红军1收到了消息;
但是这时候红军2并不确定传令军是否成功到达红军1告诉红军1收到了消息,不敢独自动手,所以红军1只好再次派出传令军,告诉红军2我们知道你们收到消息了;
问题又来了,红军1不知道传令是否成功,只有等待红军2的确认并不敢动手,红军2也只能再次派出传令军。。。

最后陷入了一个死循环,那么根本问题就暴露了:永远都不能完美的达成协议,而这正是一个一个重要的通信道理:世界上不存在完全可靠的通信协议

要解决这个问题,首先,需要知道,TCP是如何保证数据的可靠传输的

PS:TCP协议中,主动发起请求的一端称为『客户端』,被动连接的一端称为『服务端』。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据。

SYN:同步序列编号(Synchronize Sequence Numbers)。是TCP/IP建立连接时使用的握手信号。在客户机和服务器之间建立正常的TCP网络连接时,客户机首先发出一个SYN消息,服务器使用SYN+ACK应答表示接收到了这个消息,最后客户机再以ACK消息响应。这样在客户机和服务器之间才能建立起可靠的TCP连接,数据才可以在客户机和服务器之间传递。

ACK(Acknowledgement),即确认字符,在数据通信中,接收站发给发送站的一种传输类控制字符。表示发来的数据已确认接受无误。ACK信号通常是一个ASCII字符,不同的协议中ACK信号都不一样。当发送方接收到ACK信号时,就可以发送下一个数据。如果发送方没有收到信号,那么发送方可能会重发当前的数据包,也可能停止传送数据。

所以说,建立可靠连接,需要对客户端和服务器的起始序列号达成共识。

为什么不能是两次握手?

第一步:

客户端发送一个起始序列号seq = x的 报文段给服务器。

第二步:

服务器端返回向客户端发送确认号 ack = x+1,表示对客户端的起始序列号x 表示确认,

并告诉客户端,他的起始序列号是 seq = y.

所以,为什么不能两次握手?

1、这种情况下,只有服务器对客户端的起始序列号做了确认,但客户端却没有对服务器的起始序列号做确认,不能保证传输的可靠性。


2、防止失效的连接请求报文段被服务端接收,从而产生错误,浪费资源。

PS:失效的连接请求:若客户端向服务端发送的连接请求丢失,客户端等待应答超时后就会再次发送连接请求,此时,上一个连接请求就是"失效的"。

若建立连接只需两次握手,客户端并没有太大的变化,仍然需要获得服务端的应答后才进入ESTABLISHED状态,而服务端在收到连接请求后就进入ESTABLISHED状态。此时如果网络拥塞,客户端发送的连接请求迟迟到不了服务端,客户端便超时重发请求,如果服务端正确接收并确认应答,双方便开始通信,通信结束后释放连接。此时,如果那个失效的连接请求抵达了服务端,由于只有两次握手,服务端收到请求就会进入ESTABLISHED状态,等待发送数据或主动发送数据。但此时的客户端早已进入CLOSED状态,服务端将会一直等待下去,这样浪费服务端连接资源。

为什么不是四次握手?

第一步:

客户端A 发送同步信号SYN + A的初始序列号 seq = x

第二步:

服务器端B 确认收到A的同步信号,并记录A的初试序列号到本地,

并向A发送确认信息 ack =x+1。

第三步:

B发送同步信号SYN + B的初始序列号 seq 给客户端A。


第四步:

A确认收到B的同步信号,并记录 B'的初试序列号到本地,并向B发送确认信息 ack = y + 1.

很显然,第二,三步可以合并,只需要三次握手,可以提高连接的速度与效率。

总结:本质:1、保证信道数据传输的可靠性;2、避免资源浪费  3、三次是保证双方互相明确对方能收能发的最低值。

理论上讲不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数不过是提高“它是可用的”这个结论的可信程度。

TCP链接之所以可靠,是因为其链接是面向字节的。

在通信的过程中,协议会给每个字节一个序分配一个序号。三步握手的过程,主要是为了互相确认双方的起始序列号。

如果只进行两次握手,客户端发送链接请求及起始序列号seq = x, 收到 服务器端的起始序列号seq = y及对客户端序列号seq= x 的确认。此时,双方就 客户端的起始序列号达成了共识。

此时,并没有对服务器的起始序列号达成共识,所以就需要进行第三次握手。对B的起始序列号达成共识,不能保证通信的可靠。

如果进行四次握手,在四次握手的过程中,可以把第二、三步合并,这样可以提高连接的速度与效率。

ps:作为一个菜鸟程序员,本篇博文只是自己平时学习交流之用,并没有要炫耀知识的意思,如果理解有误,还望各位大佬批评指正!thank you!

 

发布了64 篇原创文章 · 获赞 47 · 访问量 9560

猜你喜欢

转载自blog.csdn.net/weixin_42194284/article/details/94313499
今日推荐