大家好,我是鸭鸭!
此答案节选自鸭鸭最近弄的面试鸭,更多大厂常问面试题,可以🔍进行阅读哈!
回答重点
来看下这个图:
具体流程文字描述就是:客户端首先发送一个SYN(同步序列编号)消息给服务器,服务器收到后回复一个SYN-ACK(同步序列编号-确认)消息,最后客户端再发送一个ACK(确认)消息确认服务器已经收到SYN-ACK消息,从而完成三次握手,建立起一个可靠的TCP连接。
扩展知识
为什么需要三次握手?
有两个原因:
- 避免历史错误连接的建立,减少通信双方不必要的资源消耗
- 帮助通信双方同步初始化序列号
避免历史错误连接的建立
RFC 793 明确指出了使用三次握手的首要原因是:为了阻止历史的重复连接初始化导致的混乱。
为什么三次能阻止这个问题?
实际上很好理解。
因为网络情况比较复杂,发送方第一次发送请求后,可能由于网络原因被阻塞住了,此时发送方可能又会再次发送请求。
如果握手只有两次,那么接收方应对发送方的请求只能拒绝或者接受,但是它无法识别当前的请求是旧的请求还是新的请求。
并且如果网络阻塞时间较长,发送方可能多次发送请求,且接收方还可能全部接受这些连接(它不清楚,以为都是有效的),这就造成了不必要的资源的浪费。
如果要避免这种情况发生,两次通信是不够的。发送方需要知晓接收方到底接受了哪个连接,如果接受的是老连接,那么发送方需要告知接收方,这个连接不对!也就是 RST 通知。如果对,那么就返回 ACK 告诉接收方 OK!这就使得一次握手至少需要 3 次。
因此三次握手,多了一次发送方确认接收方接受的连接是否正确的验证过程,所以避免了历史重复连接的错误情况。
帮助通信双方同步初始化序列号
因为网络本身的不稳定性可能为导致:
- 数据丢失
- 数据重复传输
- 数据乱序
而 TCP 是一个可靠传输协议,它需要保证数据不丢失且有序的传输。基于上述的问题,TCP 引入了序列号,它使得:
- 接收方可以根据序列号去重
- 接收方可以根据序列号排序
- 发送方针对为接收到 ACK 的序列号对应的数据包,可以重传
序列号是有序的,因此在通信的初始化阶段,双方就需要同步序列号,不然数据后面就都对不上了。
那如何同步呢?看下下面这个图:
这好像四次了?如果真的按一来一回就是四次,但是中间一步可以合并,就是接收方告知发送方收到初始序号的同时将自己的初始序号告诉发送方。
因此四次握手就可以减到三次了。
通俗理解后,我们再看下这张图:
- 发送方通过 SYN 控制消息并携带自己期望的初始序列号 SEQ 给接收方
- 接收方收到 SYN 消息之后,通过 ACK 控制消息以及 SEQ+1 来进行确认,并带上自己的 SEQ
- 发送方通过 ACK 控制消息以及接收方的 SEQ+1 来进行确认,并且还能够在第三次握手通信的同时,直接携带数据进行传输
为什么不是两次握手?
这个在上述的扩展已经解释了,因为两次握手无法阻止历史连接的建立,使得资源的浪费,也不能正确地同步序列号。
为什么不是四次握手?
理论上 3 次以上的握手都行,但是 3 次就已经够用了,没必要选择更多的握手次数。
我是鸭鸭,我们下期见~

被折叠的 条评论
为什么被折叠?



