这个问题类似于网络端口已打开,但没有进程附加?和netstat显示一个监听端口,但没有pid,但lsof不是。但它们的答案不能解决我的问题,因为它很奇怪。
我有一个名为
如您所见,监听套接字没有问题,但是当我连接数千个测试客户端(由另一位同事编写)到服务器上时,无论是2000、3000还是4000,总会有5个客户端(也是随机的)连接并向服务器发送登录请求,但无法接收任何响应。以3000个客户端为例,以下是
上面的5个连接显示它们连接到8588端口的服务器,但没有程序附加。第二列(即
上述链接提到了NFS挂载和RPC。关于RPC,我使用了命令
问题:这是怎么发生的?总是来自5个不同的客户端,我不认为这是端口冲突,因为其他客户端也连接到同一个服务器IP和端口,并且都被服务器正确处理。
注意:我正在使用Linux
< p > < em > < strong >更新 2013-06-08: 将系统升级到CentOS 6.4后,出现了同样的问题。最终我返回到使用
所以如果队列中仍有已完成的连接,为什么进程会被置于睡眠状态?
更新 2013-7-1: 在添加监听套接字时我使用了 EPOLLET,因此如果不保持 accept 直到遇到 EAGAIN,就无法全部接受。我刚意识到这个问题。是我的错。记住:如果使用 EPOLLET,即使是监听套接字,也必须 read 或 accept 直到出现 EAGAIN。再次感谢 Matthew 提供测试程序。
我有一个名为
lps
的服务器应用程序,在8588端口等待tcp连接。[root@centos63 lcms]# netstat -lnp | grep 8588
tcp 0 0 0.0.0.0:8588 0.0.0.0:* LISTEN 6971/lps
如您所见,监听套接字没有问题,但是当我连接数千个测试客户端(由另一位同事编写)到服务器上时,无论是2000、3000还是4000,总会有5个客户端(也是随机的)连接并向服务器发送登录请求,但无法接收任何响应。以3000个客户端为例,以下是
netstat
命令的输出:[root@centos63 lcms]# netstat -nap | grep 8588 | grep ES | wc -l
3000
这是 lsof
命令的输出:
[root@centos63 lcms]# lsof -i:8588 | grep ES | wc -l
2995
这里有5个连接:
[root@centos63 lcms]# netstat -nap | grep 8588 | grep -v 'lps'
tcp 92660 0 192.168.0.235:8588 192.168.0.241:52658 ESTABLISHED -
tcp 92660 0 192.168.0.235:8588 192.168.0.241:52692 ESTABLISHED -
tcp 92660 0 192.168.0.235:8588 192.168.0.241:52719 ESTABLISHED -
tcp 92660 0 192.168.0.235:8588 192.168.0.241:52721 ESTABLISHED -
tcp 92660 0 192.168.0.235:8588 192.168.0.241:52705 ESTABLISHED -
上面的5个连接显示它们连接到8588端口的服务器,但没有程序附加。第二列(即
RECV-Q
)随着客户端发送请求而不断增加。上述链接提到了NFS挂载和RPC。关于RPC,我使用了命令
rcpinfo -p
,结果与8588端口无关。而对于NFS挂载,nfssta
输出显示Error: No Client Stats (/proc/net/rpc/nfs: No such file or directory)
。问题:这是怎么发生的?总是来自5个不同的客户端,我不认为这是端口冲突,因为其他客户端也连接到同一个服务器IP和端口,并且都被服务器正确处理。
注意:我正在使用Linux
epoll
接受客户端请求。我还在我的程序中编写了调试代码,并记录了每个accept
返回的套接字(以及客户端的信息),但找不到这5个连接。这是uname -a
的输出:Linux centos63 2.6.32-279.el6.x86_64 #1 SMP Fri Jun 22 12:19:21 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
谢谢您的帮助!我真的很困惑。
< p > < em > < strong >更新 2013-06-08: 将系统升级到CentOS 6.4后,出现了同样的问题。最终我返回到使用
epoll
,并在this page上发现,将监听fd设置为非阻塞,并accept
直到返回EAGAIN
或EWOULDBLOCK
错误即可解决问题。是的,它有效了。不再有未处理连接了。但为什么呢?Unix网络编程第一卷说道:
accept is called by a TCP server to return the next completed connection from the
front of the completed connection queue. If the completed connection queue is empty,
the process is put to sleep (assuming the default of a blocking socket).
所以如果队列中仍有已完成的连接,为什么进程会被置于睡眠状态?
更新 2013-7-1: 在添加监听套接字时我使用了 EPOLLET,因此如果不保持 accept 直到遇到 EAGAIN,就无法全部接受。我刚意识到这个问题。是我的错。记住:如果使用 EPOLLET,即使是监听套接字,也必须 read 或 accept 直到出现 EAGAIN。再次感谢 Matthew 提供测试程序。
lps
是你正在编写的程序吗? - Michael Hampton