前言

  TCP和UDP是今天应用最广泛的传输层协议,拥有最核心的垄断地位。今天互联网的整个传输层,几乎都是基于这两个协议打造的。无论是应用开发、框架设计选型、做底层和优化,还是定位线上问题,只要碰到网络,就逃不开 TCP 协议相关的知识。

本章节待解决问题

Q1: TCP为什么是3次握手,4次挥手???

1. 漫游互联网:什么是蜂窝移动网络?

  网络传输需要通信链路(Communication Link),而通信链路是一个抽象概念。这里说的抽象,就是面向对象中抽象类和继承类的关系,比如同轴电缆是通信链路,无线信号的发送接收器可以构成通信链路,蓝牙信道也可以构成通信链路。在移动网络中,无线信号构成了通信链路。在移动网络的设计中,通信的核心被称作蜂窝塔(Cellular Tower),有时候也称作基站(BaseStation)。之所以有这样的名称,是因为每个蜂窝塔只覆盖一个六边形的范围,如果要覆盖一个很大的区域就需要很多的蜂窝塔(六边形)排列在一起,像极了蜜蜂的巢穴。这种六边形的结构,可以让信号无死角地覆盖。想象一下,如果是圆形结构,那么圆和圆之间就会有间隙,造成一部分无法覆盖的信号死角,而六边形就完美地解决了这个问题。

2. 传输层协议 TCP

  TCP是一个传输层协议,提供Host-To-Host数据的可靠传输,支持全双工,是一个连接导向的协议。

2.1 主机到主机(Host-To-Host)

  TCP 提供的是 Host-To-Host 传输,一台主机通过 TCP 发送数据给另一台主机。TCP 协议往上是应用到应用的协议。TCP 上层的应用层协议使用 TCP 能力的时候,需要告知 TCP 是哪个应用——这就是端口号。端口号用于区分应用TCP 要实现主机到主机通信,就需要知道主机们的网络地址(IP 地址),但是 TCP 不负责实际地址到地址(Address-To-Address)的传输,因此 TCP 协议把 IP 地址给底层的互联网层处理。互联网层,也叫网络层(Network Layer),提供地址到地址的通信。

  互联网层解决地址到地址的通信,但是不负责信号在具体两个设备间传递。因此,网络层会调用下方的链路层在两个相邻设备间传递信息。当信号在两个设备间传递的时候,科学家又设计出了物理层封装最底层的物理设备、传输介质等,由最下方的物理层提供最底层的传输能力。如下图的5层架构,我们称为互联网协议群,也称作 TCP/IP 协议群。

alt TCP/IP5层模型

2.2 什么是连接和会话?

  连接是通信双方的一个约定,目标是让两个在通信的程序之间产生一个默契,保证两个程序都在线,而且尽快地响应对方的请求,这就是连接(Connection)。

  和连接关联的还有一个名词,叫作会话(Session),会话是应用的行为。比如微信里张三和你聊天,那么张三和你建立一个会话。你要和张三聊天,你们创建一个聊天窗口,这个就是会话。你开始 Typing,开始传输数据,你和微信服务器间建立一个连接。如果你们聊一段时间,各自休息了,约定先不要关微信,1 个小时后再回来。那么连接会断开,因为聊天窗口没关,所以会话还在。

2.3 双工/单工问题

  在任何一个时刻,如果数据只能单向发送,就是单工>,所以单工需要至少一条线路。如果在某个时刻数据可以向一个方向传输,也可以向另一个方向反方向传输,而且交替进行,叫作半双工;半双工需要至少 1 条线路。最后,如果任何时刻数据都可以双向收发,这就是全双工,全双工需要大于 1 条线路。

2.4 什么是可靠性?

  可靠性指数据保证无损传输

2.5 TCP的握手和挥手

  TCP 是一个连接导向的协议,设计有建立连接(握手)和断开连接(挥手)的过程。TCP 没有设计会话(Session),因为会话通常是一个应用的行为。

2.5.1 建立连接的过程(三次握手)

  因为要保持连接和可靠性约束,TCP 协议要保证每一条发出的数据必须给返回,返回数据叫作 ACK(也就是响应)。按照这个思路,你可以看看建立连接是不是需要 3 次握手:

  1. 客户端发消息给服务端(SYN)
  2. 服务端准备好进行连接
  3. 服务端针对客户端的 SYN 给一个 ACK
  4. 服务端发送一个 SYN 给客户端
  5. 客户端准备就绪
  6. 客户端给服务端发送一个 ACK

alt TCP三次握手

  细心的同学可能会有疑问,上面不是 6 个步骤吗? 怎么是 3 次握手呢?下面我们一起分析一下其中缘由:

  步骤 1 是 1 次握手;步骤 2 是服务端的准备,不是数据传输,因此不算握手;步骤 3 和步骤 4,因为是同时发生的,可以合并成一个 SYN-ACK 响应,作为一条数据传递给客户端,因此是第 2 次握手;步骤 5 不算握手;步骤 6 是第 3 次握手。 为了方便理解步骤 3 和步骤 4,这里我画了一张图。可以看到下图中 SYN 和 ACK 被合并了,因此建立连接一共需要 3 次握手,过程如下图所示:

alt

2.5.2 断开连接的过程(4 次挥手)

  继续上面的思路,如果断开连接需要几次握手?可以在脑海中这样构思:
  1. 客户端要求断开连接,发送一个断开的请求,这个叫作(FIN)。
  2. 服务端收到请求,然后给客户端一个 ACK,作为 FIN 的响应。
  3. 这里你需要思考一个问题,可不可以像握手那样马上传 FIN 回去?
  这个情况时服务端不能马上传FIN,因为断开连接要处理的问题比较多,比如说服务端可能还有发送出去的消息没有得到 ACK;也有可能服务端自己有资源要释放。因此断开连接不能像握手那样操作——将两条消息合并。所以,服务端经过一个等待,确定可以关闭连接了,再发一条 FIN 给客户端。
  4. 客户端收到服务端的 FIN,同时客户端也可能有自己的事情需要处理完,比如客户端有发送给服务端没有收到 ACK 的请求,客户端自己处理完成后,再给服务端发送一个 ACK。

  经过以上分析,就可以回答上面这个问题了。是不是刚刚好 4 次挥手?过程如下图所示:
alt

小结

因此考虑TCP为什么是3次握手,4次挥手???

  TCP 是一个双工协议,为了让双方都保证,建立连接的时候,连接双方都需要向对方发送 SYC(同步请求)和 ACK(响应)。 握手阶段双方都没有烦琐的工作,因此一方向另一方发起同步(SYN)之后,另一方可以将自己的 ACK 和 SYN 打包作为一条消息回复,因此是 3 次握手——需要 3 次数据传输。 到了挥手阶段,双方都可能有未完成的工作。收到挥手请求的一方,必须马上响应(ACK),表示接收到了挥手请求。类比现实世界中,你收到一个 Offer,出于礼貌你先回复考虑一下,然后思考一段时间再回复 HR 最后的结果。最后等所有工作结束,再发送请求中断连接(FIN),因此是 4 次挥手。