在下面的服务器代码中调用socket之后,我收到错误“Too many open files”。这个代码被重复调用,它只在server_SD获得值1022之后才发生。所以我假设我达到了“ulimit -n”禁止的1024的限制。我不明白的是,我正在关闭Socket,它应该使fd可以重复使用,但这似乎不会发生。
注意:使用linux,是的,客户端也关闭,不,我不是root用户,所以移动限制不是一个选项,我应该一次最多打开20个(左右)套接字。在我的程序的整个生命周期中,我希望打开&接近1000000个套接字(因此需要重用非常强大的)。
server_SD = socket (AF_INET, SOCK_STREAM, 0);
bind (server_SD, (struct sockaddr *) &server_address, server_len)
listen (server_SD,1)
client_SD = accept (server_SD, (struct sockaddr *)&client_address, &client_len)
// read, write etc...
shutdown (server_SD, 2);
close (server_SD)
有谁知道如何保证关闭&可重用性?
感谢。
答案 0 :(得分:2)
从您的描述中看起来您正在为每个accept(2)
打开服务器套接字。这不是必要的。创建服务器套接字一次,bind(2)
,listen(2)
,然后循环调用accept(2)
(或者更好 - 将其提交给poll(2)
)
顺便说一下,监听套接字上的shutdown(2)
完全没有意义,它只适用于连接的套接字。
答案 1 :(得分:2)
使用valgrind
选项在--track-fds=yes
下运行您的程序:
valgrind --track-fds=yes myserver
如果您的程序使用包装器或将其置于后台,您可能还需要--trace-children=yes
。
如果它没有自行退出,请使用“kill
pid ”中断它或终止进程(不 -9
)之后它累积了一些泄露的文件描述符。退出时,valgrind
将显示仍处于打开状态的文件描述符,堆栈跟踪对应于它们的创建位置。
在strace
下运行程序以记录所有系统调用也可能会有所帮助。另一个有用的命令是/usr/sbin/lsof
-p
pid ,以显示所有当前使用的文件描述符及其用途。
答案 2 :(得分:0)
也许您的问题是您没有指定SO_REUSEADDR标志?
来自socket联机帮助页:
SO_REUSEADDR 表示验证bind(2)调用中提供的地址时使用的规则应允许重用本地地址。对于PF_INET套接字,这意味着套接字可以绑定,除非有一个绑定到该地址的活动侦听套接字。当侦听套接字绑定到具有特定端口的INADDR_ANY时,则无法将此端口绑定到任何本地地址。
答案 3 :(得分:0)
您使用的是fork()
吗?如果是这样,您的孩子可能会继承打开的文件描述符。
如果是这种情况,您应该让孩子关闭任何不属于它的fds。
答案 4 :(得分:0)
这看起来可能有“TIME_WAIT”问题。 IIRC,TIME_WAIT是TCP套接字可以处于的状态之一,并且当双方都关闭了连接时进入它,但系统保持套接字一段时间,以避免延迟消息被接受为后续连接的适当有效负载。
你可能会看一下this(第99页底部和100首)。也许是other question。
答案 5 :(得分:-1)
在关闭服务器之前需要关闭客户端(与上面的代码相反!) 谢谢所有提出建议的人!