文章目录

【注意】最后更新于 April 1, 2020,文中内容可能已过时,请谨慎使用。

  1. TCP 是一个全双工面向字节流的基于 IP 协议的协议。
  2. TCP 端到端的准确传输。
    1. 对于每一个字节进行确认
    2. 对于恶劣的网络情况的处理
      1. 超时重传
      2. 拥塞控制
    3. 效率提升
      1. 采用滑动窗口协议
  3. TCP 是一个面向连接的协议。

既然面向连接那这个连接是怎么建立的?

也就是下面的问题如果建立一个虚拟的链路采用三次握手。

三次挥手是怎么发生的

详细操作

image-20200331164958404

从码出高效扒了一张图下来,我们来讲一下三次握手的流程:

  • A 机器首先会计算出一个 seq 索引 x 表示当前发送的数据包的位置并且包的标示为 SYN。
  • B 机器接受到了这个包,并且将包中的数据存到自己的缓冲区中,因为这个包的大小为 1 字节,所以缓存区的索引是 x + 1 同步到对方的发送 seq 位置,返回一个 SYN 和 ACK 标示的包,并且将自己的发送 seq 索引 y 以及告诉对方自己收到了这个数据包所以 ack + 1。
  • C 机器收到这个带有 ACK 和 SYN 的包需要返回一个 ACK 表示自己能够收到对方的包,所以发送一个 ACK 和自己当前的发送 seq 以及自己的接受 seq。

为啥要握三次

至于为啥要握三次

主要有两点:

确保数据的对等性

  1. 首先需要确保双方的 seq 是彼此的接受与发送的缓冲区索引

  2. 确保彼此的接受和发送能力

    第三次握手能保证 B 机器的发报能力,以及 A 机器的接受能力

    image-20200331170448728

防止脏连接

image-20200331171058004

A 机器发送一个 SYN 包给 B 机器但是这个包被因为网络原因没有及时发到,又由于 TCP 的超时时间小于 TTL 因为如果 TCP 的超时间太长,那么重发封包的效率会很慢。

所以 A 机器又会发送一个 TCP,并且建立了连接,此时这个包已经到了 B 机器。

B 机器重新建立了连接,返回一个 ACK 给 A 机器。

如果只有两次握手的话,在 B 机器的视角就是已经建立了连接,但是 A 收到 B 的 Ack 的时候由于不是 SYN_SEND 所以直接丢弃,B 也无法感知,也就 B 存在单方面的脏连接了。

三次握手的话,B 需要有一次 A 的 ACK 确保自己的发送能力,同时也避免了脏连接,A 不会发送 ACK 给 B 所以 B 的视角也不会存在连接。

四次挥手是如何发生的

详细操作

image-20200331174147939

确保双方的数据都处理完成。

  • A 发送剩余数据已经 FIN 给 B 处于 FIN_WAIT
  • B 回复 ACK 给 A
  • B 等待一个 CLOSE_WAIT 再发送剩余的数据给 A
  • A 回复 ACK 表示数据收到并等待 TIME_WAIT

为啥要四次挥手

需要保证双方的数据都处理完毕,并且彼此都知道。

第三次挥手是因为 A 机器告诉 B 机器不能传输数据并且 B 机器 ACK 之后,B 机器需要等待应用程序做一个处理才能发送一个 FIN 告诉 A 机器自己不能传输数据了。

第四次挥手是告诉 B 机器自己已经接受到 B 机器无法发送请求的事实。

TCP keepalive vs Http keepalive

HTTP

Http 如果在 header 添加 keepalive = true 就会使多个 http 请求在一条 TCP 连接上,不会像之前一样一个请求握手挥手一次。

优点:

降低服务端负载,在高并发的服务器下,服务端负载会减小

降低每个 http 请求的时间,因为如果是 http 请求都会有 SSL 或者 TSL 的行为和三次握手四次挥手,所以会很慢,但是 reduce 到一个连接就不会这样了。

TCP

是 OS 来维护的,因为每个 TCP 连接都有各种各样的定时器,TCP 也有 keepalive 的定时器,当 TCP 的 keepalive 定时器到达 0 的时候,就会向对方发送一个 ACK 为开启的探测包,因为 TCP 是面向流的协议。另一方面,您将收到来自远程主机的答复。并且这两个数据包的数据为空。

优点:

判断对方是否是 dead peer

防止由于网络不活动而断开连接。

文章作者 xiantang

上次更新 2020-04-01