【发布时间】:2014-04-03 03:50:26
【问题描述】:
最近我被FD_SET缓冲区溢出两次咬了。第一次是我们有太多的套接字(1024+)要添加到FD_SET。这是一个测试用例,我们已禁用它,并添加assert 来检测此用例。
今天,当我们运行一个测试用例 1000 多次时,我们遇到了另一个相关问题。每次,测试用例都会以某种方式触发分配一个套接字,然后在测试用例完成之前释放它。当我们运行 1000+ 次时,此测试用例将遇到 FD_SET 缓冲区溢出。
我们找到了根本原因:
- 对于每一个pass,分配的socket id都会增加(+1),很长一段时间不会重复使用socket id。
Operating system是MAC,我认为避免使用已经发布的套接字而不发生错误是一个合理的设计。 -
FD_SET只设置了fd_set位数组以socket id 为索引,如果socket id 很大会溢出。我认为fd_set是一个糟糕的设计。
我们认为 1000+ 是一个合理的数字。而且我们认为定义 MACRO 来设置 'fd_set' 巨大是不合理的,并且在等待时会浪费内存和 CPU。
我们不知道如何解决它,有什么建议吗?
-------------编辑1----
原来在其他地方有套接字泄漏,这违反了析构函数应该释放所有资源。这使得套接字 id 增加。
所以项目#1 是不正确的。操作系统将重用套接字 id。
但无论如何,讨论是有帮助的,FD_SET 是糟糕的设计,我们应该使用poll()。
【问题讨论】:
-
如果它没有重用文件描述符(你称之为“socket id”),你就没有关闭文件描述符。尝试在您的测试程序运行一段时间后在其上运行
lsof。您可能会在输出中发现许多打开的套接字。 -
@JosephQuinsey,FD_SETSIZE 是 1024。
-
JosephQuinsey 和 Rob mayoff 如果你们中的任何一个人可以将您的 cmets 作为答案,我会将其掩盖为接受。
-
@robmayoff,我尝试在我的应用程序上运行 lsof,接缝套接字没有关闭,但我确定我已经从日志中调用了关闭。调用 close 函数非常简单,所以任何 cmets 为什么它不正确关闭?顺便说一句,
lsof -g PID在调试过程中不起作用,有什么原因吗? -
"... 我认为避免使用已经发布的套接字而不发生错误是一个合理的设计。" 我会说这个假设是错误的。不要使用
close()ed file-/socket-descriptors!
标签: c++ c sockets macros posix