TCP 之 三次握手 (面经计网篇)

这是tcp 简历连接的三次握手方式 , 其中的特殊符号 , 我解释下 , SYN 是 同步的这个单词(synchronization), ACK 是回执,承认的单词(acknowledgement), SYN-ACK 服务器收到SYN报文后,回复一个带有SYN和ACK标志的报文段,这表示服务器已经收到了客户端的SYN报文,并且期望收到下一个字节的序列号为服务器传递的确认号。拓展1,2,3 (介绍三个报文)

为什么是三次握手?不是两次、四次?

在前面我们知道了什么是 TCP 连接

  • 用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。

所以,重要的是为什么三次握手才可以初始化 Socket、序列号和窗口大小并建立 TCP 连接。

接下来,以三个方面分析三次握手的原因:

  • 三次握手才可以阻止重复历史连接的初始化(主要原因)
  • 三次握手才可以同步双方的初始序列号
  • 三次握手才可以避免资源浪费 (面经是这样的,但我个人感觉 , 1 和 3 是可以合并的,具体讲到了,再说)、

原因一:避免历史连接

我们来看看 RFC 793 指出的 TCP 连接使用三次握手的首要原因

The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.

简单来说,三次握手的首要原因是为了防止旧的重复连接初始化造成混乱。

我们考虑一个场景,客户端先发送了 SYN(seq = 90)报文,然后客户端宕机了,而且这个 SYN 报文还被网络阻塞了,服务端并没有收到,接着客户端重启后,又重新向服务端建立连接,发送了 SYN(seq = 100)报文(注意!不是重传 SYN,重传的 SYN 的序列号是一样的)。(这里 ,我需要自习讲解一下  只有客户端爆掉了,或者客户端出现特殊情况了,序列号才会传递一个新的 。 不然都是重传序列号

上述中的「旧 SYN 报文」称为历史连接,TCP 使用三次握手建立连接的最主要原因就是防止「历史连接」初始化了连接

这里也说明了,为什么不是两次握手:

如果是两次握手连接,就无法阻止历史连接,那为什么 TCP 两次握手为什么无法阻止历史连接呢?

我先直接说结论,主要是因为在两次握手的情况下,服务端没有中间状态给客户端来阻止历史连接,导致服务端可能建立一个历史连接,造成资源浪费

可以看到,如果采用两次握手建立 TCP 连接的场景下,服务端在向客户端发送数据前,并没有阻止掉历史连接,导致服务端建立了一个历史连接,又白白发送了数据,妥妥地浪费了服务端的资源。

因此,要解决这种现象,最好就是在服务端发送数据前,也就是建立连接之前,要阻止掉历史连接,这样就不会造成资源浪费,而要实现这个功能,就需要三次握手

所以,TCP 使用三次握手建立连接的最主要原因是防止「历史连接」初始化了连接。

原因二:同步双方初始序列号

TCP 协议的通信双方, 都必须维护一个「序列号」, 序列号是可靠传输的一个关键因素,它的作用:

  • 接收方可以去除重复的数据;
  • 接收方可以根据数据包的序列号按序接收;
  • 可以标识发送出去的数据包中, 哪些是已经被对方收到的(通过 ACK 报文中的序列号知道);

这里回答了,为什么不是四次握手:

三次,四次握手都是为了维持序列号的统一, 但看了下图,你就明白了,三次可以完成,为什么要四次来完成呢?

原因三:避免资源浪费:

这就是,我在前面说的可以和第一点合并,为什么呢?因为如果,没有防止到历史连接,自然就会有很多的序列号存在,所以,减少了历史链接,自然就避免了资源浪费 (这个“避免资源的浪费 , 基本上可以说是万金油答案”)而且还有 我自己的一些理解 ,就是通过从四次握手,减少到三次握手,会不会也减少了浪费资源

若在,握手的过程中,丢失的话,会有什么影响吗?

      第一次握手丢失了,会发生什么?

当 客户端 想和 服务端 想建立连接时,首先 , 第一次先发送SYN 报文,进入SYN-SENT 状态

在这之后,如果客户端迟迟收不到服务端的 SYN-ACK 报文(第二次握手)就会触发「超时重传」机制,重传 SYN 报文,而且重传的 SYN 报文的序列号都是一样的

通常,第一次超时重传是在1秒后,第二次超时重传是在2秒,第三次超时重传是在4秒后,第四次超时重传是在 8秒后,第五次是在超时重传 16 秒后。没错,每次超时的时间是上一次的 2倍

第二次握手丢失了,会发生什么?

当服务端收到客户端的第一次握手后,就会回 SYN-ACK 报文给客户端,这个就是第二次握手,此时服务端会进入 SYN RCVD 状态。
第二次握手的 SY-ACK 报文其实有两个目的:

  1.  第二次握手里的 ACK,是对第一次握手的确认报文;
  2.  第二次握手里的 SYN,是服务端发起建立 TCP 连接的报文,

        所以,如果第二次握手丢了,就会发生比较有意思的事情,具体会怎么样呢?


        因为第二次握手报文里是包含对客户端的第一次握手的 ACK 确认报文,所以,如果客户端迟迟没有收到第二次握手,那么客户端就觉得可能自己的 SYN 报文(第一次握手)丢失了,于是客户端就会触发超时重传机制,重传 SYN 报文 。

        然后,因为第二次握手中包含服务端的 SYN 报文,所以当客户端收到后,需要给服务端发送 ACK 确认报文(第三次握手),服务端才会认为该 SYN 报文被客户端收到了。那么,如果第二次握手丢失了,服务端就收不到第三次握手,于是服务端这边会触发超时重传机制,重传SYN-ACK 报文。

因此,当第二次握手丢失了,客户端和服务端都会重传:

  • 客户端会重传 SYN 报文,也就是第一次握手,最大重传次数由 tcp_syn_retries 内核参数决定
  • 服务端会重传 SYN-ACK 报文,也就是第二次握手,最大重传次数出 tcp_synack_retries 内核参数决定。

第三次握手丢失了,会发生什么?

        客户端收到服务端的 SYN-ACK 报文后,就会给服务端回一个 ACK 报文,也就是第三次握手,此时客户端状态进入到 ESTABLISH 状态
        因为这个第三次握手的 ACK 是对第二次握手的 SYN 的确认报文,所以当第三次握手丢失了,如果服务端那一方迟迟收不到这个确认报文,就会触发超时重传机制,重传SYN-ACK 报文,直到收到第三次握手或者达到最大重传次数。
        注意,ACK 报文是不会有重传的,当 ACK丢失了,就由对方重传对应的报文
举个例子,假设 tcp_synack_retries 参数值为 2,那么当第三次握手一直丢失时,发生的过程如下图:

上诉都参考我之前看过的文章

拓展 1 :

拓展 2 :

拓展 3 :

  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值