c++ - 关闭套接字不释放文件描述符

标签 c++ linux sockets ulimit

在对我编写的一些服务器代码进行压力测试时,我注意到即使我在描述符句柄上调用 close()(并验证结果是否有错误),描述符也没有被释放,这最终会导致 accept()返回错误“太多打开的文件”。

现在我明白这是因为 ulimit,但我不明白的是,如果我在每个同步接受/读取/发送周期后调用 close(),为什么会命中它?

我正在通过使用 lsof 运行 watch 来验证描述符确实存在:

ctsvr  9733 mike 1017u  sock     0,7      0t0 3323579 can't identify protocol
ctsvr  9733 mike 1018u  sock     0,7      0t0 3323581 can't identify protocol
...

果然有大约 1000 个左右。此外,通过 netstat 检查我可以看到没有挂起的 TCP 状态(没有 WAIT 或 STOPPED 或任何东西)。

如果我只是从客户端执行一个连接/发送/接收,我会注意到套接字确实保留在 lsof 中;所以这甚至不是负载问题。

服务器在 Ubuntu Linux 64 位机器上运行。

有什么想法吗?

最佳答案

所以使用 strace(感谢 Gearoid),我不知道没有它我是怎么生活的,我注意到我实际上是在关闭描述符。

但是。为了后代,我揭露了我的愚蠢错误:

Socket::Socket() : impl(new Impl) {
    impl->fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    ....
}

Socket::ptr_t Socket::accept() {
    auto r = ::accept(impl->fd, NULL, NULL);
    ...
    ptr_t s(new Socket);
    s->impl->fd = r;
    return s;
}

如您所见,我的构造函数立即分配了一个套接字,然后我用 accept 返回的描述符替换了描述符——造成了泄漏。我已将接受代码从独立的 Acceptor 类重构到 Socket 类中,但没有更改它。

使用 strace 我可以很容易地看到 socket() 每次都在运行,这导致了我的灯泡时刻。

感谢大家的帮助!

关于c++ - 关闭套接字不释放文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12820976/

相关文章:

c++ - atoi(str) 中的段错误

c++ - 无法将 ‘char**’ 转换为 ‘char*’

c++ - Qt QUdpSocket : readyRead() signal and corresponding slot not working as supposed

c++ - 新的运营商 ->有或没有

c++ - C++中的切换栈

linux - 如何使用 shell 脚本在空白文件的特定行号处添加行

linux - 将shell脚本的参数分成几个会导致错误

linux - 从另一个动态库加载的动态库中的重复符号

Android充当wifi服务器集线器?

c++ - 将调用推送到 STL 队列 <std::string> 会在从套接字读取字符串时导致段错误