【计算机网络】三次握手与四次挥手

三次握手与四次挥手

通过TCP/IP协议的学习,我们可以知道TCP协议是一种面向连接的、可靠的传输协议。其中,为了保证客户端与服务器连接的有效性,就有了本篇文章所要介绍的“三次挥手”;而“四次挥手”则是为了保证连接的正确断开。

1. TCP状态

首先,介绍一下TCP的几个状态:

  • SYN —— 同步序列编号,在建立连接时发送
  • ACK —— 确认信息,在确认SYN信息时发送,响应信息
  • FIN —— 关闭连接
  • RST —— 连接重置
  • PSH —— 有数据传输
  • URG —— 紧急指针字段值有效

2. 三次握手

建立TCP连接时会经过如下步骤:

  • 服务器准备接收客户端连接(通过socket API),由于连接是由客户端激发的,因此称为被动打开
  • 客户端调用connect开始主动打开,并发送SYN(syn = i)包,告诉服务器发送数据的序列号
  • 服务器确认(ACK,ack = i+1)客户端发来的信息(SYN),并发送SYN(syn = j),其中含有服务器发送数据的初始序列号。注:SYNACK是同时发送的,在一个数据包中
  • 客户端确认服务器发送的SYN,发送ACK(ack = j+1)数据包

其中,因为SYN需要占据一个字节的序列号空间,因此ACK中确认号为发来的SYN序列号加1;类似,FIN的ACK确认号为该FIN序列号加1。

1

3. 四次挥手

  • 某进程先调用close,该端TCP发送FIN(fin = i),表示数据发送完毕,需要关闭连接。称为主动关闭
  • 接收到FIN的对端执行被动关闭。进行确认(ACK, ack = i+1),在该进程接收的其他所有数据之后添加文件结束符(end-of-file)
  • 一段时间之后(因为要处理已经接收到的数据),接收到文件结束符的进程调用close关闭套接字,这导致它的TCP也发送FIN(fin = j)
  • 主动关闭连接的一端确认(ACK, ack = j+1)最后发送的FIN

2

为什么建立连接要三次握手,而断开连接要四次挥手?

建立连接时,因为发起连接的一端在发出请求后,连接建立之前,就不会再发出任何数据,因此接收连接请求的对端可以将ACK、SYN放在一个数据包里发回给请求端,即需要三次数据发送。而断开连接时,在一端主动断开连接并发送FIN包后,对端接收到发来的FIN包,进行确认(ACK),然而此时服务器可能还在给另一端发送数据,只有在数据发送完后才能断开连接,发送FIN包(所以不能像三次握手时那样将ACK、SYN同时发送),另一端收到FIN后再进行确认并发送ACK,因此需要四次数据发送。

TCP建立的连接为全双工通道,可以双向传输数据,因此在建立连接、断开连接时,需要两端都要进行请求与确认。

为什么建立连接的ACK、SYN可以同时发送,而断开连接则需要分开发送?

建立、断开连接都需要两次请求与确认,只是建立连接时SYN、ACK可以同时发回,而在断开连接时,由于被动关闭的一端可能还会发送数据,只有数据发完后才能发送ACK,所以只能分开发送,也就造成了建立连接为三次,断开连接反而成了四次。(建立连接时由于握手期间连接未完全建立,故不能发送其他数据)