用C编写Linux服务器的最佳方法(phteads、select或fork?)

Best approach for writing a Linux Server in C (phtreads, select or fork ? )

本文关键字:select phteads fork 方法 编写 Linux 服务器 最佳      更新时间:2023-10-16

我收到了一个关于UNIX中服务器编程的非常具体的问题(Debian,内核2.6.32)。我的目标是学习如何编写一个可以处理大量客户端的服务器。我的目标是超过3万个并发客户(即使我的大学提到可能有50万个,这似乎是一个巨大的数字:-),但我真的不知道(甚至不知道什么是可能的),这就是我在这里问的原因。所以我的第一个问题。可能同时有多少个客户端?客户端可以随时连接,并与其他客户端取得联系,组成一个组(1个组最多包含12个客户端)。他们可以相互聊天,因此TCP/IP包的大小因发送的消息而异。客户端还可以向服务器发送数学公式。服务器将解决这些问题,并将答案广播回小组。这是一项相当繁重的工作。

我目前的做法是启动服务器。而不是使用fork来创建守护进程。守护进程绑定套接字fd_listen并开始侦听。这是一个while(1)循环。我使用accept()来获取来电。

一旦客户端连接,我就会为该客户端创建一个pthread,该客户端将运行通信。客户端被添加到一个组中,并一起共享一些内存(保持组运行所需),但仍然每个客户端都在不同的线程上运行。正确访问内存是一件很困难的事情,但现在效果很好。

在程序的开头,我读取了/proc/sys/kernel/threads max文件,并根据该文件创建了线程。根据该文件,可能的线程数量约为5000个。与我希望能够服务的客户数量相去甚远。我考虑的另一种方法是使用select()并创建集合。但是在一个集合中查找套接字的访问时间是O(N)。如果我有超过几千个客户端连接,这可能会很长时间。如果我错了,请纠正我。

好吧,我想我需要一些想法:-)

GroetjesMarkus

附言:我把它标记为C++和C,因为它适用于这两种语言。

目前最好的方法是像libevlibevent这样的事件循环

在大多数情况下,您会发现一个线程绰绰有余,但即使不是,您也可以始终使用多个具有独立循环的线程(至少使用libev)。

Libev[ent]为每个操作系统使用最高效的轮询解决方案(任何都比select或每个套接字一个线程更高效)。

您将遇到几个限制:

  1. fd_set大小:在编译时可以更改,但默认情况下限制很低,这会影响select解决方案
  2. 每个套接字的线程早就用完了——我建议将长度计算放在单独的线程中(如果需要,可以使用池),但否则单线程方法可能会扩展

要达到500000,你需要一套机器,我怀疑还有循环DNS。

只要服务器没有连接回客户端,TCP端口就不会成为问题。我似乎总是忘记这一点,必须提醒我。

我认为,文件描述符本身应该不会有太大问题,但将它们纳入你的民意调查解决方案可能会更困难——当然你不想每次都传递它们。

我认为可以使用事件模型(epoll+工作线程池)来解决这个问题。首先在主线程中侦听并接受,如果客户端连接到服务器,则主线程将clientfd分发给一个工作线程,并添加epoll列表,然后该工作线程将处理来自客户端的reqeust。

工作线程的数量可以由问题配置,并且不能超过5000。