【问题标题】:Socket server with epoll and threads带有 epoll 和线程的套接字服务器
【发布时间】:2012-01-07 22:43:26
【问题描述】:

我正在尝试用 C 语言为协作式实时编辑器 http://en.wikipedia.org/wiki/Collaborative_real-time_editor 创建一个套接字服务器,但我不知道最适合它的服务器架构是什么。

一开始,我尝试将 select 用于套接字服务器,但在那之后,我阅读了有关 epoll 的内容,现在我认为 epoll 是最好的选择,因为客户端会发送用户将写入的每一个字母textarea,到服务器,所以服务器将分配数据来处理。

另外,我想在 epoll 中使用线程,但我不知道如何使用它们。我想使用线程,因为我认为在目标机器上使用 2 个或所有 CPU 会更好。

我的计划是

  • 服务器启动时创建2个线程

  • 第一个线程将分析新客户端并为读取或发送做好准备

  • 第二个线程将负责从/向客户端读取和发送数据

问题是这 2 个线程将使用带有 epoll_wait 的 while(1)。

我的问题是,这是一个使用 epoll 和线程的好服务器架构吗?如果没有,我有什么选择?

编辑:我不能使用 libeventlibev 或其他库,因为这是一个大学项目,我不允许使用外部库。

【问题讨论】:

  • 我建议不要使用 epoll,因为它不是普遍可用的,并且您在弄清楚架构时从简单的东西开始。此外,如果您有大量连接,epoll 也很好,但是当您只有几个连接时,响应时间就没有关系了。
  • 除非你设法使 CPU 的一个核心饱和,否则没有理由去多线程。为此,您需要 10,000 个客户(如果您的应用程序编写得很好)。

标签: c multithreading sockets pthreads epoll


【解决方案1】:

我认为你试图过度设计这个问题。 Linux 中的epoll 体系结构适用于具有数千个并发连接的情况。在这些情况下,定义pollselect 系统调用的开销将成为服务器的主要瓶颈。使用pollselectepoll 的决定取决于连接数,而不是数据量。

对于您正在做的事情,您编辑系统中的人员似乎会在您遇到几十个并发编辑器后发疯。使用epoll 可能会让你发疯;他们使用 API 玩了一些技巧来挤出额外的性能,并且您必须非常小心地处理从调用中返回的信息。

这种应用程序听起来像是受网络 I/O 限制而不是 CPU 限制。我会先尝试将其编写为带有poll 的单线程服务器。当您收到新文本时,如有必要,为您的客户端缓冲它,然后在套接字接受write 调用时将其发送出去。使用非阻塞 I/O;您要阻止的唯一呼叫是 poll 呼叫。

如果您在接收到数据后,但在将其发送回客户端之前对其进行大量处理,那么您可以从多线程中受益。先写单线程版本,然后如果你受 CPU 限制(使用 top 检查)并且大部分 CPU 时间花在你正在处理数据的函数上(使用 gprof 检查),添加多线程到进行数据处理。

如果您愿意,您可以在程序中使用管道或 Unix 域套接字来进行不同线程之间的通信——这样,主线程中的一切都可以被事件驱动和处理通过poll。或者,使用此模型,您甚至可以使用 fork 的多个进程而不是多个线程。

【讨论】:

    【解决方案2】:

    只需开始使用libeventlibev 并按照他们的示例进行操作。有很多例子——不要试图在这里发明任何新东西

    【讨论】:

    • 有时尝试自己动手可以让人们欣赏系统的复杂性,并更加欣赏 API 的易用性,同时也减少使用更高级别 API 时可能出现的意外.如果这是一个大学项目,我会说去原始民意调查/选择/epoll!
    【解决方案3】:

    您可能需要考虑使用 libevlibevent 之类的东西,而不是编写自己的事件处理实现。这些为您提供了一个跨平台的事件处理程序,它将使用任何合适的东西(无论是selectpollepollkqueue 还是其他任何东西),并且很可能比让两个线程切换的开销更低互相合作。

    【讨论】:

    • 如何使用 libeven 或 libev 来利用所有可用的处理器?有标准的方法吗?
    • @SlappyTheFish:根据我对工作负载的理解,可能没有必要。即使是相当幼稚的 select 实现也可能会起作用,因为这主要是 I/O 绑定的。此外,假设 TCP,每个字母单独发送的问题实际上并不存在(除非强制,例如使用 TCP_NODELAY 或类似的)。
    • @Hasturkun 我忘了在我的主要帖子中提到,我不能使用 libevent 或 libev,因为这是一个大学项目,我不允许使用任何外部库。
    • @bugspy.net 他们只教我们普通的 C 例如这是他们添加 epoll 的一年,在过去的几年里没有提到 epoll 只有 select 和 poll。 :)
    • @cemycc:对于这种情况,一个简单的单线程服务器可能工作得很好,除非您需要这样做。您可以使用相同的selectpoll 循环来接受新连接并从连接的套接字发送/接收数据。我建议您将套接字设置为非阻塞以防止出现一些意外(例如,select 表示 recv 不会阻塞,但随后的 recv 会阻塞,这可能发生在 UDP 中)
    猜你喜欢
    • 1970-01-01
    • 2017-05-29
    • 2012-01-08
    • 1970-01-01
    • 2012-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多