2

在下面的服务器代码中调用套接字后,我收到错误“打开的文件太多”。此代码被重复调用,并且仅在 server_SD 获得值 1022 之后才发生。所以我假设我达到了“ulimit -n”所禁止的 1024 的限制。我不明白的是我正在关闭套接字,这应该使 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)

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

谢谢。

4

6 回答 6

2

valgrind使用以下--track-fds=yes选项运行您的程序:

valgrind --track-fds=yes myserver

--trace-children=yes如果您的程序使用包装器或将自身置于后台,您可能还需要。

如果它没有自行退出,则在累积一些泄露的文件描述符后,中断它或使用“ kill pid ”(not )终止进程。 -9退出时,valgrind将显示仍然打开的文件描述符以及与它们创建位置相对应的堆栈跟踪。

在下运行您的程序strace以记录所有系统调用也可能会有所帮助。另一个有用的命令是/usr/sbin/lsof -p pid显示所有当前使用的文件描述符以及它们的用途。

于 2009-08-05T19:36:43.400 回答
2

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

编辑0:

顺便说一句,shutdown(2)监听套接字完全没有意义,它仅适用于连接的套接字。

于 2009-08-05T16:13:00.660 回答
0

看起来您可能遇到“TIME_WAIT”问题。IIRC,TIME_WAIT是TCP套接字可以处于的状态之一,当双方都关闭连接时进入,但系统会保留套接字一段时间,以避免延迟消息被接受为后续连接的正确有效负载。

你也许应该看看这个(第 99 页的底部和 100 页的顶部)。也许还有其他问题

于 2009-08-05T11:36:16.530 回答
0

也许您的问题是您没有指定 SO_REUSEADDR 标志?

套接字手册页:

SO_REUSEADDR 表示用于验证 bind(2) 调用中提供的地址的规则应该允许重用本地地址。对于 PF_INET 套接字,这意味着一个套接字可以绑定,除非有一个活动的侦听套接字绑定到该地址。当侦听套接字使用特定端口绑定到 INADDR_ANY 时,就不可能为任何本地地址绑定到该端口。

于 2009-08-05T10:54:47.567 回答
0

你在用fork()吗?如果是这样,您的孩子可能会继承打开的文件描述符。如果是这种情况,您应该让孩子关闭任何不属于它的 fd。

于 2009-08-05T11:07:03.953 回答
-1

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

于 2009-08-05T19:34:37.617 回答