一、现象
linux系统中运行了一个TCP服务器,该服务器监听的TCP端口为10000。但是长时间运行时发现该端口会崩溃,TCP客户端连接该端口会失败:
可以看到进行三次握手时,TCP客户端向该TCP服务器的10000端口发送了SYN报文,但是TCP服务器返回了RST报文。此时我们用netstat命令查看到10000端口没有被监听了,这意味着该端口被关闭或者不在监听中了。
二、排查思路
服务器发送RST包的原因可能有以下几种:
连接重置:当服务器主动关闭连接时,它会发送RST包。
收到非法数据包:当服务器收到一个不符合协议规则的数据包时,它可能会发送RST包。
防火墙规则:服务器的防火墙规则可能会拦截特定的数据包,并发送RST包。
连接拒绝:当服务器拒绝客户端的连接请求时,它可能会发送RST包。
其他原因:可能是由于网络硬件故障或其他原因导致的。
一开始我们以为是服务器的网络架构原因导致端口被关闭。但我们注意到端口被关闭时日志不断打印信息:“msg:socket(): Too many open files”。出现这个报错的大多数情况都是文件句柄(file handle)泄露,通俗的说就是文件句柄在不断的被打开,但是在使用完成之后却没有正常的关闭导致文件打开数不断的增加。文件句柄泄露有多种原因,而不仅仅是打开文件,常见的来源有:套接字,管道,数据库连接,文件。这可能意味着我们的程序打开了太多文件没有关闭导致同时打开的文件数超出了系统的限制。
为了验证我们的猜想,我们不断查看服务器进程目前打开的句柄数量:lsof -p 进程ID | wc -l
可以看到服务器进程打开的句柄数量不断上升,说明确实是因为服务器进程在某个时刻打开了超过系统限制的文件数量或者通讯链接数导致的。
阅读服务器代码:
可以看到上述代码中,调用了fopen函数后,没有调用对应的fclose函数进行文件的关闭,所以导致了该问题的产生。我们把fclose函数加上去,即解决了该问题。
三、参考
【Linux】报错 too many open file
socket: too many open files
Too many open files (CLOSE_WAIT过多)的解决方案:修改打开文件数的上限值、调整TCP/IP的参数 原创
程序 too many open files 问题排查及解决
Socket accept - "Too many open files"