Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 单线程服务器还是多线程服务器最好?_C_Linux_Network Programming - Fatal编程技术网

C 单线程服务器还是多线程服务器最好?

C 单线程服务器还是多线程服务器最好?,c,linux,network-programming,C,Linux,Network Programming,我必须使用C语言(Linux)创建一个简单的clientserver通信来传输文件 服务器在10000端口上接受连接,我不知道是为每个请求创建一个新线程,还是创建固定数量的线程并使用异步技术更好 CASE A: client --> server --> (new thread) --> process the request CASE B: SERVER --> create thread 1 - thread 2 - thread 3 then client

我必须使用C语言(Linux)创建一个简单的clientserver通信来传输文件

服务器在10000端口上接受连接,我不知道是为每个请求创建一个新线程,还是创建固定数量的线程并使用异步技术更好

CASE A:

client --> server --> (new thread) --> process the request

CASE B:

SERVER --> create thread 1 - thread 2 - thread 3

then

client1 --> server --> thread 1
client2 --> server --> thread 2
client3 --> server --> thread 3
client4 --> server --> thread 1
client5 --> server --> thread 2
client6 --> server --> thread 3
在这种情况下,线程1可以处理许多客户端的请求

我的考虑:

案例1:速度更快,但会浪费大量内存

情况2:速度较慢,但内存不足


我错了吗?

这完全取决于你。答案没有对错之分。你已经确定了两者的优点和缺点,你对这两个都是正确的;1更快但更密集,2较慢,因为客户端可能需要等待

我会使用预先创建的线程池,并在处理完当前请求后重新使用它们。创建线程可能很昂贵,因为它主要涉及对内核的调用


有一个使用pthreads的“threadpool”类型的项目。也许你可以从那里得到一些关于如何实施的想法。

这里没有正确的答案。这取决于很多事情。你需要自己选择

“案例1:速度更快,但会浪费大量内存
“情况2:速度较慢,但内存不足”

错。这取决于很多事情。创建线程没有那么贵(是的,但没有那么贵),但是如果线程太多,你就会有问题

这在很大程度上取决于负载-预期负载是多少?如果是,比如说,大约每秒1000个请求-你知道,如果你每秒创建1000个线程…这将是灾难:D

另外-创建CPU能够处理的线程数,而不在线程之间进行(大量)切换。单核CPU使用10个线程而不是1个线程(或2个线程)工作的速度非常慢,这也很大程度上取决于这些线程的功能


我会选择创建一个线程池并重用线程。

我的第一个选择是使用select(2)实现单线程。 如果这在性能方面还不够好,我会选择线程池解决方案。 它将更好地扩展

有时,为每个客户机创建一个线程是完全可以的。
我已经完成了这项工作,它对这个应用程序很有效,通常有大约100个客户最多1000个客户。这是15年前的事。今天,同一个应用程序可能由于更好的硬件而处理10000个客户机。只需知道每个客户机的一个线程不能很好地扩展。sed http服务器(nginx、lighttpd、apache)您会注意到,使用固定线程数的服务器(所谓的“工作线程”,其数量应取决于服务器上的处理器数)比使用大型线程池的服务器快很多。但是,有非常重要的时刻:

  • “工作线程“实施不应该像诱人的那样简单,否则就不会有真正的性能提升。每个线程应该使用状态机实现每个伪并发,一次处理多个请求。这里不允许任何阻塞操作—例如,线程中等待来自硬盘驱动器的I/O获取文件内容的时间可用于解析下一个客户端的请求。不过,编写这段代码相当困难

  • 当考虑性能、编码时间和代码支持时,基于线程的解决方案(具有可重用的线程池,因为线程创建是重量级操作)是最优的。如果您的服务器不应该每秒处理数千个请求,那么您将能够以非常自然的阻塞方式编写代码,而不会冒性能完全失败的风险

  • 正如您所注意到的,“工作线程”解决方案本身只服务于静态数据,它们将动态脚本执行代理给其他一些程序。据我所知(可能是错误的),这是由于请求的非阻塞处理的复杂性,在它们的上下文中执行了一些未知的动态内容。无论如何,在您的情况下,这不应该是一个问题,因为您谈论的是简单的文件传输

  • 有限线程解决方案在重载系统上速度更快的原因是线程是一个非常昂贵的操作,因为它需要保存寄存器中的数据并加载新的寄存器,以及一些其他线程本地数据。如果与进程计数相比,您有太多的线程(比如1000倍以上),那么应用程序中的大量时间将被浪费在线程之间的切换上

    因此,对您的问题的简短回答是:“不,这与内存使用无关,选择的重点是所服务的数据类型、计划的请求/秒数以及花费大量时间进行编码的能力。”

    这实际上取决于您的服务器在做什么

    我建议你尽可能做最简单的事情。这可能是一个单一的进程模型,它使用、select、poll、libevent或类似方法多路复用所有可用的连接

    也就是说,如果您使用的是TCP


    如果你使用UDP,它会更容易,因为应用程序可以用一个套接字做任何事情,所以它可以(可能)使用阻塞套接字。

    我知道你问这个问题已经有一段时间了,但是我从一个已经用C写过一些服务器的人的角度来回答你的问题

    如果您的服务器是您自己的、完全依赖并且不依赖于其他代码,我将高度推荐您使用非阻塞套接字并使用epoll(Linux)、kqueue(BSD)或WSAEventSelect(Windows)来执行单线程

    这可能需要您将原本“简单”的代码拆分为更小的代码块,但如果您考虑的是可伸缩性,那么这将胜过任何基于线程/基于选择的服务器

    有一个伟大的梦想