Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题( 四 )



Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
本文插图
第二个报文 —— SYN + ACK 报文

  • 服务端收到客户端的 SYN 报文后 , 首先服务端也随机初始化自己的序号(server_isn) , 将此序号填入 TCP 首部的「序号」字段中 , 其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYN 和 ACK 标志位置为 1 。 最后把该报文发给客户端 , 该报文也不包含应用层数据 , 之后服务端处于 SYN-RCVD 状态 。

Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
本文插图
第三个报文 —— ACK 报文
  • 客户端收到服务端报文后 , 还要向服务端回应最后一个应答报文 , 首先该应答报文 TCP 首部 ACK 标志位置为 1, 其次「确认应答号」字段填入 server_isn + 1, 最后把报文发送给服务端 , 这次报文可以携带客户到服务器的数据 , 之后客户端处于 ESTABLISHED 状态 。
  • 服务器收到客户端的应答报文后 , 也进入 ESTABLISHED 状态 。
从上面的过程可以发现第三次握手是可以携带数据的 , 前两次握手是不可以携带数据的 , 这也是面试常问的题 。
一旦完成三次握手 , 双方都处于 ESTABLISHED 状态 , 此致连接就已建立完成 , 客户端和服务端就可以相互发送数据了 。
如何在 Linux 系统中查看 TCP 状态?
TCP 的连接状态查看 , 在 Linux 可以通过 netstat -napt 命令查看 。
Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
本文插图
TCP 连接状态查看
为什么是三次握手?不是两次、四次?
相信大家比较常回答的是:“因为三次握手才能保证双方具有接收和发送的能力 。 ”
这回答是没问题 , 但这回答是片面的 , 并没有说出主要的原因 。
在前面我们知道了什么是 TCP 连接:
  • 用于保证可靠性和流量控制维护的某些状态信息 , 这些信息的组合 , 包括Socket、序列号和窗口大小称为连接 。
所以 , 重要的是为什么三次握手才可以初始化Socket、序列号和窗口大小并建立 TCP 连接 。
接下来以三个方面分析三次握手的原因:
  • 三次握手才可以阻止历史重复连接的初始化(主要原因)
  • 三次握手才可以同步双方的初始序列号
  • 三次握手才可以避免资源浪费
原因一:避免历史连接
我们来看看 RFC 793 指出的 TCP 连接使用三次握手的首要原因:
The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.
简单来说 , 三次握手的首要原因是为了防止旧的重复连接初始化造成混乱 。
网络环境是错综复杂的 , 往往并不是如我们期望的一样 , 先发送的数据包 , 就先到达目标主机 , 反而它很骚 , 可能会由于网络拥堵等乱七八糟的原因 , 会使得旧的数据包 , 先到达目标主机 , 那么这种情况下 TCP 三次握手是如何避免的呢?
Java:吊打面试官!近 40 张图解被问千百遍的 TCP 三次握手和四次挥手面试题
本文插图
三次握手避免历史连接
客户端连续发送多次 SYN 建立连接的报文 , 在网络拥堵等情况下: