三次握手和四次挥手

说这个之前要先认识一下TCP的头部格式


image.png
  • 序列号(Seq Num):在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。

  • 确认应答号(Ack Num):指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决不丢包的问题。

  • 控制位:
    ACK:该位为 1 时,「确认应答」的字段变为有效,TCP 规定除了最初建立连接时的 SYN 包之外该位必须设置为 1 。
    RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
    SYN:该位为 1 时,表示希望建立连接,并在其「序列号」的字段进行序列号初始值的设定。
    FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。当通信结束希望断开连接时,通信双方的主机之间就可以相互交换 FIN 位置为 1 的 TCP 段。

TCP连接的三次握手

TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手而进行的。

图片

一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态

第一次握手:

  • 客户端会随机初始化序号 (client_isn)
  • 将此序号置于 TCP 首部的「序号」字段中(Seq Num=client_isn),同时把 SYN 标志位置为 1 ,表示 SYN 报文
  • 客户端发送 SYN 包到服务器,表示向服务端发起连接,该报文不包含应用层数据
  • 进入 SYN_SEND 状态,等待服务器确认;

第二次握手:

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

第三次握手:

  • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文
  • 首先该应答报文 TCP 首部 ACK 标志位置为 1
  • 其次「确认应答号」字段填入 server_isn + 1
  • 最后把报文发送给服务端,这次报文可以携带客户到服务器的数据
  • 此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。

从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的题。

一旦完成三次握手,双方都处于 ESTABLISHED 状态,此致连接就已建立完成,客户端和服务端就可以相互发送数据了。

四次挥手

image.png
  • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。

  • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。

  • 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。

  • 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。

  • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态

  • 服务器收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。

  • 客户端在经过 2MSL(报文最大生存时间) 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。

你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

摘至

你可能感兴趣的:(三次握手和四次挥手)