TCP/IP-三次握手和四次挥手

作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!

在日常分析和定位生产环境的问题时,经常会碰到各种各样的网络问题,查看应用监听端口上连接的数量、各种状态的连接数量分布成为常用的手段之一。但一些同学看不懂使用netstat过滤出来的各种状态是什么含义以及各种状态的连接数量分布可能存在什么问题。其实只要弄懂了TCP/IP建立连接(即三次握手)和关闭连接(即四次挥手),上面的问题迎刃而解。

一、建立连接(三次握手)

三次握手
  1. 第一次握手:建立连接时,客户端发送SYN(seq=x)包到服务器,并进入SYN_SENT状态,等待服务器的确认。SYN:同步序列编号(Synchronize Sequence Numbers)。
  2. 第二次握手:服务器收到SYN包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即发送SYN+ACK包,此时服务器进入SYN_RECV状态
  3. 第三次握手:客户端收到SYN+ACK包,向服务器发送ACK(ack=y+1)包,此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据。下面是通过Wirkshark抓包得到的TCP/IP三次握手的数据包截图:
三次握手的Wirkshare抓包

说明:

  • 10.0.2.15是建立请求的发起方(即客户端)。
  • 42.121.252.58是建立请求的接收方(即服务端)。

为什么建立连接要三次握手?

目的: 防止已经失效的连接请求到达服务端,创建无效的连接,浪费资源。
说明: 当客户端发出的第一个连接请求在网络上的某个节点被滞留了(网络会存在许多不可靠的因素),过一段时间后突然又到达了服务端,服务端误以为这是一个新的建立连接的请求,于是就会向客户端发出确认包并建立连接。
实际上客户端当前并没有发出创建连接的请求,就会丢弃服务端的确认包。而服务端却创建了连接并等待客户端发送数据,浪费了相关的资源。

三次握手存在的风险

攻击方伪造IP地址发送大量的SYN包,使服务端发送的SYN+ACK包得不到确认,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源,服务器失去响应,即服务器端受到了SYN Flood攻击。

二、关闭连接(四次挥手)

四次挥手

注:挥手动作可由客户端或服务器任意一方发起。

  • 第一次挥手:客户端发送FIN+ACK包(序号为seq=a,确认序号ack=b)给服务端,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态。
  • 第二次挥手:服务端收到FIN+ACK包后,发送ACK包给客户端进行确认,服务端进入CLOSE_WAIT状态。客户端收到ACK包后进入FIN_WAIT_2状态。到这里,关闭一个单向通道。
  • 第三次挥手:服务端发送FIN+ACK包给客户端,服务端进入LAST_ACK状态。
  • 第四次挥手:客户端收到FIN+ACK包后,发送ACK包给服务端进行确认,客户端进入TIME_WAIT状态,在等待30秒(可修改)后进入CLOSED状态。服务端收到ACK包后进入CLOSED状态,关闭另一个单向通道。

下面是通过Wirkshark抓包得到的TCP/IP四次挥手的数据包截图:
四次挥手的Wirkshare抓包

说明:

  • 42.121.252.58是关闭请求的发起方(即客户端)。
  • 10.0.2.15是关闭请求的接收方(即服务端)。

为什么关闭连接要四次挥手?

TCP是全双工通道,一方发起关闭请求只关闭了一个方向上的通道,所以建立连接的双方都要发起关闭请求并确认来关闭各自方向上的数据通道。

三、三次握手和四次挥手状态扭转

三次握手和四次挥手状态扭转