查看主机tcp目前的状态
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TCP状态迁移原理以及各个问题原因和解决方案
- tcp三次握手和四次挥手的状态转移图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cttu3rVJ-1590219517606)(https://s1.51cto.com/images/20180824/1535100611422858.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)] - close_wait过多原因
close_wait 按照正常操作的话应该很短暂的一个状态,接收到客户端的fin包并且回复客户端ack之后,会继续发送fin包告知客户端关闭关闭连接,之后迁移到Last_ACK状态。但是close_wait过多只能说明没有迁移到Last_ACK,也就是服务端是否发送fin包,只有发送fin包才会发生迁移,所以问题定位在是否发送fin包。fin包的底层实现其实就是调用socket的close方法,这里的问题出在没有执行close方法。说明服务端socket忙于读写。
- close_wait过多的解决方案
- 代码层面做到第一:使用完socket调用close方法;第二:socket读控制,当读取的长度为0时(读到结尾),立即close;第三:如果read返回-1,出现错误,检查error返回码,有三种情况:INTR(被中断,可以继续读取),WOULDBLOCK(表示当前socket_fd文件描述符是非阻塞的,但是现在被阻塞了),AGAIN(表示现在没有数据稍后重新读取)。如果不是AGAIN,立即close
- 可以设置TCP的连接时长keep_alive_time还有tcp监控连接的频率以及连接没有活动多长时间被迫断开连接
- Time_Wait停留时间长的原因(2MSL大约1-4分钟,数据包在IP传输的最长生命时长)
- 为了防止最后一个ACK没有送到服务端,如果客户端立即关闭的话,服务端会重新发fin包,这时客户端关闭,服务端会收到RST,也就是一个报错
- 为了防止当前连接中的重复报文干扰下一个连接