TCP的11种状态、三次握手/四次挥手、TIME_WAIT/CLOSE_WAIT

版权声明:guojawee https://blog.csdn.net/weixin_36750623/article/details/84951261

在这里插入图片描述

查看TCP状态:netstat -nap

三次握手

  1. 服务器调用listen系统函数,进入LISTEN状态
  2. 客户端向服务器发送SYN段请求连接后,进入SYN_SEND状态
  3. 一旦监听到某个连接请求(受到SYN段),就将该连接放入内核等待队列种,并向客户端发送SYN+ACK,此时服务器处于SYN_RECV状态
  4. 客户端发送ACK给服务器&&服务器接收到客户端发来的ACK后,二者都进入ESTABLISH状态

SYN洪水攻击

SYN洪水攻击(雅虎网站)
原理:三次握手的漏洞
(1)伪造大量的虚假的IP地址向服务器发送连接请求syn=a
(2)服务器接收到连接请求后,将连接请求加入未连接队列中,并回复ack=a+1和syn=b
(3)由于IP地址是虚假的,因此不会给服务器回复ack=b+1
(4)使服务器不断的给IP地址重发syn=b,造成服务器网络拥塞
(5)由于未连接队列被占满,导致新来的请求被丢弃

四次挥手

  1. 客户端向服务器发送FIN段,说明自己不再向服务器发送数据(但是可以从服务器接收数据),然后进入FIN_WAIT_1状态
  2. 服务器接收到客户端发来的FIN段后,再返回ACK报文段后,进入CLOSE_WAIT状态
  3. 客户端接收到服务器返回的ACK报文段后,进入FIN_WAIT_2状态
  4. 当服务器显示的调用close、shutdown关闭自身连接时,服务器将向客户端发送FIN段,然后进入LAST_ACK状态
  5. 此时客户端收到服务器发送来的FIN段后,进入TIME_WAIT状态。
  6. 最后客户端将发送ACK通知服务器,我已经收到你发送的FIN,当服务器接收到最后一个ACK时,进入CLOSED状态。此时,全双工的通信管道真正的断开

CLOSE_WAIT状态

Note1 ⇒半关闭状态: 被动方一直处于CLOSE_WAIT状态,主动方一直处于FIN_WAIT_2状态,状态不能继续推进

Note2 ⇒ 为什么一直处于半关闭状态? 为什么一直处于半关闭状态?被动关闭方没显示的调用shutdown、close去关闭连接
因此:当检测到大量的CLOSE_WAIT和FIN_WAIT_2状态时,往往是服务器程序引发的,应检查服务器程序在客户端关闭连接(服务器程序在read返回0)后是否显示的调用close函数关闭自身连接。

Note3 ⇒ 客户端执行半关闭后,如果未等服务器关闭连接就强行退出了,此时客户端连接将由内核来接管,可称之为孤儿连接(类似于孤儿进程)。Linux为了防止孤儿连接长时间存留在内核中,定义了两个内核变量:/proc/sys/net/ipv4/tcp_max_orphans 、 /proc/sys/net/ipv4/tcp_fin_timeout,分别表示"内核能接管的孤儿连接数目"、“孤儿连接在内核中生存的时间”。

Note4 ⇒如何防止大量的CLOSE_WAIT状态出现? 从检测不到对方已经断开入手!
1.服务器代码需要判断socket,一旦read返回0,断开连接,read返回负,检查一下errno,如果不是AGAIN,也断开连接
2.使用一个Heart-Beat线程,定期向socket发送指定格式的心跳数据包,如果接收到对方的RST报文,说明对方已经关闭了socket,那么我们也关闭这个socket。
3.设置SO_KEEPALIVE选项,并修改内核参数

TIME_WAIT状态

参考《TIMEWAIT状态》一文:https://blog.csdn.net/weixin_36750623/article/details/84949809

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/84951261
今日推荐