TCP:握手次数辨析与拓展

1,109 阅读5分钟

问题背景

“为什么TCP要握手3次挥手要4次”是一道很常见的面试题。以前笔者一直不明白这个问题有什么好问的,而且看了大部分博客的答案好像就是说连接过程的(对答案不是很满意啊);现在自己作答希望能把逻辑讲圆,欢迎大家留言批评指正:)

阅读本文前建议快速scan一下《三个角度看TCP连接建立与结束》作为基础知识的预热。

本文先说握手。

最少交换3次

先看连接建立过程中的三次握手,这里先摆出结论: "The minimum number of packets required for this exchange is three; hence, this is called TCP's three-way handshake." (引用网络编程大神已故的Richard Stevens) 我这里神翻译下:连接建立要交换信息,交换信息最少需要3个数据包,也称之为3次握手

这句话进一步解释一下(important!)

  • 不能少于3次,因为少于3次信息交完不完,所以不可能是0,1,2;
  • 3次可以传够信息
  • 多余3次当然可以把信息交换清楚,而且TCP握手过程却是也可以出现这种情况,但3次是最少也是最常见的交换模式;

交换的是什么

Richard Stevens原话中有一个关键词是exchange(交换),但exchange的是什么呢?

TCP设计了sequence number,ack,MSS,advertised window等机制, 这些机制需要在数据传输前先约定好初始值,这些初始值的交换至少需要两个TCP segment;同时TCP中采用了ack机制来保证传达,所以还需要最后一个单独的ack和中间和信息一起发的ack确认两边初始信息都正确传达了。

>3次?

小于3次的问题很清晰了,不多赘述了; 多于3次的问题可以再多说两句,认知要点有三个,总结一句大白话是:一般1没必要2浪费,但有一些情况会出现

双向连接分开一个个建立变成4次握手并没有什么必要TCP正常的使用场景是C-S架构模式下的双边通信:只有一边发送的场景并不是常见场景,所以并没有需求先建一个单向的half-connection再看情况建另一个half-connection;此外一般是C端主动发起连接,也不常见S也一起发起主动连接。这个是为什么连接建立时不用断开时的4次。(这里相关的两个话题是4次挥手为什么不是3次,还有就是另一个协议叫做SCTP的握手为什么是4次,后面我们分析)

传输效率

啰嗦的语言可能也能转达信息,但是信息输出密度就低很多了。沟通是有成本的,时间、带宽和kernel的处理能力。

多次握手确实存在

什么时候多次握手会出现,其实看过TCP状态机的大家都应该见识过,可能只是没有从这个角度来思考吧。对比一下上面正常三次握手的图,和链接建立过程的状态机会发现状态机中的信息量是远远超过3次握手的。其中一组多出的信息是passive open,active open和simultaneous open。

在三次握手的时候一端(通常是client端)主动发起连接,称为active open(主动连接);另一端(通常是服务端)被动接收sync,称为passive open(被动连接)。在一种比较少见的使用场景里,两端互相知道对方的ip+port,在接收对方的sync前分别向对方发sync包,这中连接方式称为simultaneous open (simultaneous是同时的意思)。

具体4次握手可以参考上图,这时候两方连接是对称的,都经历了sync_send和sync_received状态。simultaneous open存在但是十分少见:因为这种连接方式需要两端都知道对方的ip+port并主动发sync包;而tcp主要用于C-S的架构,在CS架构下,C端一般没有公网ip没法直接从server端主动建立路由规则。

握手次数的本质

讲到这里TCP为什么3次握手其实已经讲完了,再精炼一下。握手次数核心在于1)连接建立需要双方交互的信息,注意这里的信息不是量的问题,大白话讲就是要交换几趟/个来回信息才能满足这个通信协议的机制启动),和2)加一个ack,往往最后一个ack没法合并

下面讲一个4次握手的协议来强化一下这个核心道理的提炼:))

正常就4次握手的协议

在传输层除了UDP和TCP之外第三名可能是SCTP协议,这种协议正常的连接建立就是4次握手。这里需要多一次的原因是除了sync的双向确认,还需要cookie的双向确认;sync的双向确认主动发起的是client端,cookie是server端下发;sync 3次,cookie 3次,把6次中中间能合并在“一趟”里的信息合并成为4次

SCTP前两次交换了核心信息:Ta,Tz;J,K(相当于tcp中的ISN);Cookie。并ack了客户端的int。四次的争议在于最后两次是不是可以缩减成1次。设计成3次其实可以work,相当于带cookie防止DDoS的TCP连接;但是设计成4次可以兼顾安全与效率:

  • 新增了cookie的校验过程,server回复ack才认为cookie被服务端认可并以cookie内的信息创建了连接(这个是cookie模式与前文TCP安全模式中sync backlog模式不同的点,cookie模式可以防止DDoS攻击);
  • 同时新增了ack使得cookie校验过程中可以进行数据夹带,这样ack同时可以确认数据,在增加了一个segment之后同时也提高了效率。