用C编写Linux服务器的最佳方法(phteads、select或fork?)
Best approach for writing a Linux Server in C (phtreads, select or fork ? )
我收到了一个关于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,因为它适用于这两种语言。
目前最好的方法是像libev
或libevent
这样的事件循环。
在大多数情况下,您会发现一个线程绰绰有余,但即使不是,您也可以始终使用多个具有独立循环的线程(至少使用libev)。
Libev[ent]为每个操作系统使用最高效的轮询解决方案(任何都比select
或每个套接字一个线程更高效)。
您将遇到几个限制:
fd_set
大小:在编译时可以更改,但默认情况下限制很低,这会影响select
解决方案- 每个套接字的线程早就用完了——我建议将长度计算放在单独的线程中(如果需要,可以使用池),但否则单线程方法可能会扩展
要达到500000,你需要一套机器,我怀疑还有循环DNS。
只要服务器没有连接回客户端,TCP端口就不会成为问题。我似乎总是忘记这一点,必须提醒我。
我认为,文件描述符本身应该不会有太大问题,但将它们纳入你的民意调查解决方案可能会更困难——当然你不想每次都传递它们。
我认为可以使用事件模型(epoll+工作线程池)来解决这个问题。首先在主线程中侦听并接受,如果客户端连接到服务器,则主线程将clientfd分发给一个工作线程,并添加epoll列表,然后该工作线程将处理来自客户端的reqeust。
工作线程的数量可以由问题配置,并且不能超过5000。
- SQLite3 在 c++ 中输出 SELECT 上的空列表
- 如何在 sys/select.h 中正确使用
- 获取具有字段名称的 SELECT 字段类型,并带有 MariaDB C++连接器
- UDP 套接字 select() 在某些情况下无延迟(超时)返回 1
- Winsock2 select():同一个套接字上可能有多个事件吗?
- Winsock2 select() 返回 WSAEINVAL(错误 10022)
- 将 select() 与非基于文件描述符的输入一起使用
- Winsock2 select() 函数:传递 {0, 0} 作为超时参数
- 如何在C++应用程序中设置"Select Precision"光标?
- C++11 中对超载'ref(Select::Expressions::Code&)'的调用模棱两可
- 使用 select() 管理多个套接字
- 如何应用注册表模式使"select class depend on input"遵守开放封闭原则?
- 使用 Select 多路复用未命名的管道和其他文件描述符
- 为什么在使用 select() 时连接到带有第二个套接字的服务器"break"第一次连接?
- read() 在 select() 阻塞之后,当从生成的进程从管道读取时
- win32 select()报告插入()套接字上的例外;wsagetlasterror()= 0
- 使用SEND()之前,请使用Select()检查套接字
- 使用 select() 和大量文件描述符的外部代码
- MinGW64和"conflicting declaration of C function int select(...)"
- 用C编写Linux服务器的最佳方法(phteads、select或fork?)