【转】为什么 TCP 建立连接需要三次握手

原文作者:draveness
原文链接:为什么 TCP 建立连接需要三次握手 (建议前往原文以获得最佳体验)

为什么这么设计(Why’s THE Design)是一系列关于计算机领域中程序设计决策的文章,我们在这个系列的每一篇文章中都会提出一个具体的问题并从不同的角度讨论这种设计的优缺点、对具体实现造成的影响。如果你有想要了解的问题,可以在文章下面留言。

TCP 协议是我们几乎每天都会接触到的网络协议,绝大多数网络连接的建立都是基于 TCP 协议的,学过计算机网络或者对 TCP 协议稍有了解的人都知道 —— 使用 TCP 协议建立连接需要经过三次握手(three-way handshake)。

如果让我们简单说说 TCP 建立连接的过程,相信很多准备过面试的人都会非常了解,但是一旦想要深究『为什么 TCP 建立连接需要三次握手?』,作者相信大多数人都没有办法回答这个问题或者会给出错误的答案,这边文章就会讨论究竟为什么我们需要三次握手才能建立 TCP 连接?

需要注意的是我们会将重点放到为什么需要 TCP 建立连接需要『三次握手』,而不仅仅是为什么需要『三次』握手。

概述

在具体分析今天的问题之前,我们首先可以了解一下最常见的错误类比,这个对 TCP 连接过程的错误比喻误导了很多人,作者在比较长的一段时间内也认为它能够很好地描述 TCP 建立连接为什么需要三次握手:

  1. 你听得到吗?
  2. 我能听到,你听得到?
  3. 我也能听到;

这种用类比来解释问题往往就会面临『十个类比九个错』的尴尬局面,如果别人用类比回答你的为什么,你需要仔细想一想它的类比里究竟哪里有漏洞;类比带来的解释往往只能有片面的相似性,我们永远也无法找到绝对正确的类比,它只在我们想要通俗易懂地展示事物的特性时才能发挥较大的作用,我们在文章的后面会介绍为什么这里的类比有问题,各位读者也可以带着疑问来阅读剩下的内容。

很多人尝试回答或者思考这个问题的时候其实关注点都放在了三次握手中的三次上面,这确实很重要,但是如果重新审视这个问题,我们对于『什么是连接』真的清楚?只有知道连接的定义,我们才能去尝试回答为什么 TCP 建立连接需要三次握手。

The reliability and flow control mechanisms described above require that TCPs initialize and maintain certain status information for each data stream. The combination of this information, including sockets, sequence numbers, and window sizes, is called a connection.

RFC 793 - Transmission Control Protocol 文档中非常清楚地定义了 TCP 中的连接是什么,我们简单总结一下:用于保证可靠性和流控制机制的信息,包括 Socket、序列号以及窗口大小叫做连接。

所以,建立 TCP 连接就是通信的双方需要对上述的三种信息达成共识,连接中的一对 Socket 是由互联网地址标志符和端口组成的,窗口大小主要用来做流控制,最后的序列号是用来追踪通信发起方发送的数据包序号,接收方可以通过序列号向发送方确认某个数据包的成功接收。

到这里,我们将原有的问题转换成了『为什么需要通过三次握手才可以初始化 Sockets、窗口大小和初始序列号?』,那么接下来我们就开始对这个细化的问题进行分析并寻找解释。

设计

这篇文章主要会从以下几个方面介绍为什么我们需要通过三次握手才可以初始化 Sockets、窗口大小、初始序列号并建立 TCP 连接:

  • 通过三次握手才能阻止重复历史连接的初始化;
  • 通过三次握手才能对通信双方的初始序列号进行初始化;
  • 讨论其他次数握手建立连接的可能性;

这几个论点中的第一个是 TCP 选择使用三次握手的最主要原因,其他的几个原因相比之下都是次要的原因,我们在这里对它们的讨论只是为了让整个视角更加丰富,通过多方面理解这一有趣的设计决策。

历史连接

RFC 793 - Transmission Control Protocol 其实就指出了 TCP 连接使用三次握手的首要原因 —— 为了阻止历史的重复连接初始化造成的混乱问题,防止使用 TCP 协议通信的双方建立了错误的连接。

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

想象一下这个场景,如果通信双方的通信次数只有两次,那么发送方一旦发出建立连接的请求之后它就没有办法撤回这一次请求,如果在网络状况复杂或者较差的网络中,发送方连续发送多次建立连接的请求,如果 TCP 建立连接只能通信两次,那么接收方只能选择接受或者拒绝发送方发起的请求,它并不清楚这一次请求是不是由于网络拥堵而早早过期的连接。

所以,TCP 选择使用三次握手来建立连接并在连接引入了 RST 这一控制消息,接收方当收到请求时会将发送方发来的 SEQ+1 发送给对方,这时由发送方来判断当前连接是否是历史连接:

  • 如果当前连接是历史连接,即 SEQ 过期或者超时,那么发送方就会直接发送 RST 控制消息中止这一次连接;
  • 如果当前连接不是历史连接,那么发送方就会发送 ACK 控制消息,通信双方就会成功建立连接;
    使用三次握手和 RST 控制消息将是否建立连接的最终控制权交给了发送方,因为只有发送方有足够的上下文来判断当前连接是否是错误的或者过期的,这也是 TCP 使用三次握手建立连接的最主要原因。

初始序列号

另一个使用三次握手的重要的原因就是通信双方都需要获得一个用于发送信息的初始化序列号,作为一个可靠的传输层协议,TCP 需要在不稳定的网络环境中构建一个可靠的传输层,网络的不确定性可能会导致数据包的缺失和顺序颠倒等问题,常见的问题可能包括:

  • 数据包被发送方多次发送造成数据的重复;
  • 数据包在传输的过程中被路由或者其他节点丢失;
  • 数据包到达接收方可能无法按照发送顺序;

为了解决上述这些可能存在的问题,TCP 协议要求发送方在数据包中加入『序列号』字段,有了数据包对应的序列号,我们就可以:

  • 接收方可以通过序列号对重复的数据包进行去重;
  • 发送方会在对应数据包未被 ACK 时进行重复发送;
  • 接收方可以根据数据包的序列号对它们进行重新排序;

序列号在 TCP 连接中有着非常重要的作用,初始序列号作为 TCP 连接的一部分也需要在三次握手期间进行初始化,由于 TCP 连接通信的双方都需要获得初始序列号,所以它们其实需要向对方发送 SYN 控制消息并携带自己期望的初始化序列号 SEQ,对方在收到 SYN 消息之后会通过 ACK 控制消息以及 SEQ+1 来进行确认。

如上图所示,通信双方的两个 TCP A/B 分别向对方发送 SYN 和 ACK 控制消息,等待通信双方都获取到了自己期望的初始化序列号之后就可以开始通信了,由于 TCP 消息头的设计,我们可以将中间的两次通信合成一个,TCP B 可以向 TCP A 同时发送 ACK 和 SYN 控制消息,这也就帮助我们将四次通信减少至三次。

A three way handshake is necessary because sequence numbers are not tied to a global clock in the network, and TCPs may have different mechanisms for picking the ISN’s. The receiver of the first SYN has no way of knowing whether the segment was an old delayed one or not, unless it remembers the last sequence number used on the connection (which is not always possible), and so it must ask the sender to verify this SYN. The three way handshake and the advantages of a clock-driven scheme are discussed in [3].

除此之外,网络作为一个分布式的系统,其中并不存在一个用于计数的全局时钟,而 TCP 可以通过不同的机制来初始化序列号,作为 TCP 连接的接收方我们无法判断对方传来的初始化序列号是否过期,所以我们需要交由对方来判断,TCP 连接的发起方可以通过保存发出的序列号判断连接是否过期,如果让接收方来保存并判断序列号却是不现实的,这也再一次强化了我们在上一节中提出的观点 —— 避免历史错连接的初始化。

通信次数

当我们讨论 TCP 建立连接需要的通信次数时,我们经常会执着于为什么通信三次才可以建立连接,而不是两次或者四次;讨论使用更多的通信次数来建立连接往往是没有意义的,因为我们总可以使用更多的通信次数交换相同的信息,所以使用四次、五次或者更多次数建立连接在技术上都是完全可以实现的。

这种增加 TCP 连接通信次数的问题往往没有讨论的必要性,我们追求的其实是用更少的通信次数(理论上的边界)完成信息的交换,也就是为什么我们在上两节中也一再强调使用『两次握手』没有办法建立 TCP 连接,使用三次握手是建立连接所需要的最小次数。

总结

我们在这篇文章中讨论了为什么 TCP 建立连接需要经过三次握手,在具体分析这个问题之前,我们首先重新思考了 TCP 连接究竟是什么,RFC 793 - Transmission Control Protocol - IETF Tools 对 TCP 连接有着非常清楚的定义 —— 用于保证可靠性和流控制机制的数据,包括 Socket、序列号以及窗口大小。

TCP 建立连接时通过三次握手可以有效地避免历史错误连接的建立,减少通信双方不必要的资源消耗,三次握手能够帮助通信双方获取初始化序列号,它们能够保证数据包传输的不重不丢,还能保证它们的传输顺序,不会因为网络传输的问题发生混乱,到这里不使用『两次握手』和『四次握手』的原因已经非常清楚了:

『两次握手』:无法避免历史错误连接的初始化,浪费接收方的资源;
『四次握手』:TCP 协议的设计可以让我们同时传递 ACK 和 SYN 两个控制信息,减少了通信次数,所以不需要使用更多的通信次数传输相同的信息;
我们重新回到在文章开头提的问题,为什么使用类比解释 TCP 使用三次握手是错误的?这主要还是因为,这个类比没有解释清楚核心问题 —— 避免历史上的重复连接。到最后,我们还是来看一些比较开放的相关问题,有兴趣的读者可以仔细想一下下面的问题:

除了使用序列号是否还有其他方式保证消息的不重不丢?
UDP 协议有连接的概念么,它能保证数据传输的可靠么?
如果对文章中的内容有疑问或者想要了解更多软件工程上一些设计决策背后的原因,可以在博客下面留言,作者会及时回复本文相关的疑问并选择其中合适的主题作为后续的内容。

Reference

RFC 793 - Transmission Control Protocol - IETF Tools
Why do we need a 3-way handshake? Why not just 2-way?

(0)

相关推荐

  • 淘宝二面,面试官居然把TCP三次握手问的这么详细

    TCP 的三次握手和四次挥手,可以说是老生常谈的经典问题了,通常也作为各大公司常见的面试考题,具有一定的水平区分度.看似是简单的面试问题,如果你的回答不符合面试官期待的水准,有可能就直接凉凉了. 本文 ...

  • Wireshark数据抓包分析之传输层协议(TCP协议)

    使用TCP协议传输数据相对来说更安全,因为通信双方拥有一个专属的通信通道,每发送一个数据包都有确认回复,若数据包丢失.如果发送放没收到确认包,就可以重发这个数据包. 最经典的例子就是三次握手.三次握手 ...

  • TCP ,丫的终于来了!!

    之前的文章一直在聊各种网络协议,那么从这篇文章开始,我就会和你聊一聊关于 TCP 协议的种种特征,比如 TCP 连接管理(也是这篇文章主要讨论的).TCP 超时和重传.TCP 拥塞控制.TCP 数据流 ...

  • TCP协议:SYN、ACK、ISN、SeqNumber

    0. 前言 在网络分析中,读懂TCP序列号和确认号的值,可以帮助我们学习TCP协议以及排查问题,如通过查看序列号和确认号可以确定数据传输是否乱序. 在网络分析中,读懂TCP序列号和确认号的值,可以帮助 ...

  • 万字详文彻底弄懂TCP协议:从三次握手和四次挥手说起

    作者:morganhuang,腾讯 IEG 后台开发工程师 说到 TCP 协议,相信大家都比较熟悉了,对于 TCP 协议总能说个一二三来,但是 TCP 协议又是一个非常复杂的协议,其中有不少细节点让人 ...

  • 为什么TCP 要采用「3次握手」建立连接?1个例子教会你~

    首先说说为什么是三次握手? 当客户端发送一次请求A后,但是A在网络延迟了很久, 接着客户端又发送了一次B,但是此时A已经无效了. 接着服务器相应了B,并返回TCP连接头,建立连接(这里就2次哈). 然 ...

  • 吕梁:方山县建立“两包三到”精准帮扶联动机制

    为扎实推进精准扶贫工作,方山县统筹包村领导.驻村工作队和第一书记三支力量,建立单位包村.领导包带和工作队到村.党员干部到户.第一书记到岗的"两包三到"联动帮扶机制. 推行单位包村责 ...

  • 钢筋连接的三种方式:绑扎、焊接、机械,如何选择?

    钢筋连接方式选择的正确是否直接关系到工程质量的优劣,现结合规范.标准对三种常见的钢筋连接方式进行分析对比:①绑扎搭接.②焊接连接.③机械连接,以方便工程设计和施工人员正确选用. 一 绑扎搭接 钢筋绑扎 ...

  • 如何与你的身体建立连接?分享5个方法

    作为'现代人',许多人都与自己的身体失去了联结... 这会表现为: 身体明明想要休息,却继续熬夜看手机,追剧... 身体明明饱了,却依然欲求不满而吃进去更多... 身体明明想离开一个能量浑浊的地方,却 ...

  • tcp为什么要三次握手,四次挥手

    为什么不能两次握手:(防止已失效的连接请求又传送到服务器端,因而产生错误) 假设改为两次握手,client端发送的一个连接请求在服务器滞留了,这个连接请求是无效的,client已经是closed的状态 ...

  • 大白话告诉你 TCP 为什么需要三次握手四次挥手

    关于 TCP 的三次握手和四次挥手相比大家早就烂熟于心了,毕竟这也是一个高频的面试题,但是很多小伙伴只是照本宣科,并没有真正的理解其中的原理,这篇文章,阿粉用通俗易懂的大白话带你们重新熟悉一下,已经掌 ...

  • 如何将电视机与Sound Bar建立连接? | Sony China

    依据电视机与音频系统的不同,连接方式也有差异. 根据如下的连接方式,可以选择适合您的方式. 注意: 以下连接以HT-CT660为例,视您的机型而定,接口可能有所不同,具体可参考产品的说明书. 视型号而 ...