TCP的三次握手和四次挥手

前言

TCP的三次握手和四次挥手常作为面试题考察程序员对于TCP握手协议的理解。该篇文章写于2018年, 此处为博客迁移,无内容增删。

TCP三次握手

假设 A 为客户端,B 为服务器端。

  1. 首先 B 处于 LISTEN(监听)状态,等待客户的连接请求。
  2. A 向 B 发送连接请求报文段,SYN=1,ACK=0,选择一个初始的序号 x。
  3. B 收到连接请求报文段,如果同意建立连接,则向 A 发送连接确认报文段,SYN=1,ACK=1,确认号为 x+1,同时也选择一个初始的序号 y。
  4. A 收到 B 的连接确认报文段后,还要向 B 发出确认,确认号为 y+1,序号为 x+1。
  5. B 收到 A 的确认后,连接建立。

说明:

  • SYN(synchronous)是TCP/IP建立连接时使用的握手信号.
  • ACK (Acknowledgement)即是确认字符.TCP报文格式中的控制位由6个标志比特构成,其中一个就是ACK,ACK为1表示确认号有效,为0表示报文中不包含确认信息,忽略确认号字段。
  • seq 是序列号,是为了连接以后传送数据用的,初始随机.
  • ack 是期望对方继续发送的那个数据包的序列号.因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1

举个例子

  • 第一次(A—>B),SYN=1,seq=x
  • 第二次(B—>A),SYN=1,ACK=1,seq=y,ack=x+1 //seq为什么是y,ack为什么是x+1?
  • 第三次(A—>B),ACK=1,seq=x+1,ack=y+1 //seq为什么是x+1,ack为什么是y+1?
1
2
3
4
5
seq是序列号,这是为了连接以后传送数据用的,ack是对收到的数据包的确认,值是等待接收的数据包的序列号。

在第一次消息发送中,A随机选取一个序列号作为自己的初始序号发送给B;第二次消息B使用ack对A的数据包进行确认,因为已经收到了序列号为x的数据包,准备接收序列号为x+1的包,所以ack=x+1,同时B告诉A自己的初始序列号,就是seq=y;第三条消息A告诉B收到了B的确认消息并准备建立连接,A自己此条消息的序列号是x+1,所以seq=x+1,而ack=y+1是表示A正准备接收B序列号为y+1的数据包。

seq是数据包本身的序列号;ack是期望对方继续发送的那个数据包的序列号。

TCP四次挥手

以下描述不讨论序号和确认号,因为序号和确认号的规则比较简单。并且不讨论 ACK,因为 ACK 在连接建立之后都为 1。

  1. A 发送连接释放报文段,FIN=1;
  2. B 收到之后发出确认,此时 TCP 属于半关闭状态,B 能向 A 发送数据但是 A 不能向 B 发送数据;
  3. 当 B 要不再需要连接时,发送连接释放请求报文段,FIN=1;
  4. A 收到后发出确认,此时连接释放。