插座&文件描述符重用(或缺少)

时间:2009-08-05 10:48:40

标签: linux networking sockets reusability file-descriptor

在下面的服务器代码中调用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)

有谁知道如何保证关闭&可重用性?

感谢。

6 个答案:

答案 0 :(得分:2)

从您的描述中看起来您正在为每个accept(2)打开服务器套接字。这不是必要的。创建服务器套接字一次,bind(2)listen(2),然后循环调用accept(2)(或者更好 - 将其提交给poll(2)

编辑0:

顺便说一下,监听套接字上的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)

在关闭服务器之前需要关闭客户端(与上面的代码相反!) 谢谢所有提出建议的人!