关于处理超过 1024 个套接字描述符

Posted

技术标签:

【中文标题】关于处理超过 1024 个套接字描述符【英文标题】:Regarding handling more than 1024 socket descriptors 【发布时间】:2012-06-18 04:22:47 【问题描述】:

我在 Linux 上使用 C 语言编写了一个聊天服务器。我已经测试过了,它在性能方面工作得很好。唯一滞后的是我正在使用 select 系统调用来处理套接字描述符。由于 select 的限制为 1024,所以我的聊天服务器最多只能同时处理 1024 个用户。

我知道我可以使用的另一个选项是 poll,但与 select 相比,我不太确定它及其性能。

请建议我解决这种情况的最有效方法。

【问题讨论】:

Handling more than 1024 file descriptors, in C on Linux的可能重复 肯定使用 epoll 而不是 select Christian.K 上面提供的链接明确地为这个问题提供了解决方案。 在我的程序中我可以重新定义 __FD_SETSIZE 因为 fdset 从系统文件中获取它 【参考方案1】:

poll() 可以用作select() 的几乎直接替代品,并且允许您超过 1024 个文件描述符(您可以使传递给poll() 的数组尽可能大)。

它将具有与select() 相似的性能特征,因为两者都需要内核和用户空间应用程序来扫描整个阵列 - 但如果select() 对您来说工作正常,那么poll() 也应该如此。 (实际上poll() 的性能略有提升——.events 字段,为每个文件描述符指定您感兴趣的事件,不会被poll() 更改,因此您不必在之前重建数组每次调用都像你对传递给select()的文件描述符集所做的那样。

如果以后发现自己因为扫描 poll 文件描述符数组而导致性能问题,可以考虑切换到epoll 接口,该接口更复杂,但对于非常多的文件描述符也可以更好地扩展。

【讨论】:

【参考方案2】:

Linux 对 select() 没有 1024 个限制。但是:

    select() 性能很差 FreeBSD 可以:)

你可以使用 poll()。但是当活动连接数增加时,它的性能会受到影响。

在 Linux 上使用 epoll() 更好,但我建议使用 libevent

libevent 是实现重负载服务器的快速、干净和可移植的方式,对于 linux,它具有 epoll。

【讨论】:

【参考方案3】:

您的问题被称为C10K problem(如何处理超过 1 万个同时连接)。你会在网上找到很多资源,例如this one.

您应该将select 视为过时的系统调用。即使只有几十个文件描述符,你至少应该更喜欢poll

请注意,Qt 和 Gtk 为您提供了事件循环机制,通常使用 poll(并且 QtCore 或 Glib 可以在 图形 界面之外使用)。还有libev 和libevent。我建议使用其中之一。

【讨论】:

以上是关于关于处理超过 1024 个套接字描述符的主要内容,如果未能解决你的问题,请参考以下文章

关于套接字描述符

我们如何将文件描述符限制为始终小于 1024?

高性能网络编程 - select系统调用

套接字描述符就绪条件

我可以在同一个套接字描述符上调用 bind() 然后 connect() 吗?

描述符就绪条件