我正在尝试编写一个能够在C语言中同时处理多个(超过一千个)客户端连接的服务器。每个连接都意味着完成三件事:
我正在使用非阻塞套接字和epoll()来处理所有连接,但是我的问题恰好在服务器从一个客户端接收数据并且必须调用一个花费几秒钟处理数据的函数之后。数据返回之前返回必须在关闭连接之前发送回客户端的结果。
我的问题是,我可以使用哪种范例,以便在一个客户的数据“正在烹饪”时能够继续处理更多连接?
我一直在研究通过每次创建一个线程或一个进程我需要调用计算函数来实现它的可能性,但我不确定这是否会考虑到可能的并发连接的数量,这就是为什么我来到这里期望有更多经验的人可以解释我的无知。
代码段:
while (1)
{
ssize_t count;
char buf[512];
count = read (events[i].data.fd, buf, sizeof buf); // read the data
if (count == -1)
{
/* If errno == EAGAIN, that means we have read all
data. So go back to the main loop. */
if (errno != EAGAIN)
{
perror ("read");
done = 1;
}
/* Here is where I should call the processing function before
exiting the loop and closing the actual connection */
answer = proc_function(buf);
count = write (events[i].data.fd, answer, sizeof answer); // send the answer to the client
break;
}
...
提前致谢。
答案 0 :(得分:1)
多线程或多进程在某种程度上实现这一目标似乎是明智的。多线程或多进程的程度是问题。
1)您可以完全转储轮询系统并使用每个连接的线程/进程。只要它想要处理该连接的处理,该线程就可以停止。然后,您必须决定每次创建/终止线程/进程(可能最简单)或拥有一个线程/进程池(可能最快)。
2)您可以为网络位创建一个线程/进程,并将处理交给另一个线程。这不太平行,但它确实意味着您可以至少在处理工作列表时继续处理网络连接。这使您可以控制至少处理的处理。以这种方式对传入连接进行优先级排序很容易,而选项1可能不会。
3)(可能的1& 2)您可以使用异步I / O来多路连接。您仍然可以像1& 1那样处理处理。 2以上。
您还有线程与进程的问题。线程可能更快开始,但确保数据完整性更加困难。流程将更具弹性,但需要更多接口。
您还必须决定在线程/进程之间传递数据的方法。这不是选项1的问题,因为您只需要传递与线程的连接。选项2可能(取决于您的数据)更多的是问题。您可以使用消息队列来传递消息,但如果您有大量数据要发送共享内存则更合适。共享内存对于进程来说是一种痛苦的工程,但是线程很容易(因为所有线程共享相同的内存空间)。
当你达到这种规模时,也存在性能问题。值得研究这些东西的性能特征。当您处理大量连接时,选择和轮询比例等调用的差异很大。
如果不知道发送和接收的数据,很难提供可靠的建议。
顺便说一下,这不是一个新问题。几年前Dan Kegel有一个good article。它现在已经过时了,但概述仍然很好。你应该研究他所讨论的概念的现有技术水平。