鉴于这个例子,与使用多个线程或进程相比,我从轮询设计中得到啥好处?
Posted
技术标签:
【中文标题】鉴于这个例子,与使用多个线程或进程相比,我从轮询设计中得到啥好处?【英文标题】:Given this example, what do I benefit from the poll design, compared to using multiple threads or processes instead?鉴于这个例子,与使用多个线程或进程相比,我从轮询设计中得到什么好处? 【发布时间】:2020-03-11 17:00:28 【问题描述】:最近一直在学习socket编程,终于在Beej's Guide to Network Programming找到了一些很好的例子。
在poll
section 下有一个使用poll
的聊天服务器示例。
代码:
charsever.c(聊天服务器接收客户端消息并将消息发送给所有其他客户端)
当我逐行阅读代码并完全理解示例后,我突然意识到设计是多么巧妙和整洁。
基本上,它使用poll
监视所有内容,服务器侦听套接字accept
用于新传入的TCP 连接和所有现有的TCP 套接字。不需要额外的线程或进程。
然后我开始问自己:
看来我可以使用多个进程(如果太复杂,可以使用多个线程)来达到相同的效果。以聊天服务器为例,设计可以是:
主进程处理新的传入 TCP 连接并将新的连接套接字添加到全局数组all_sockets
。
对于主进程中的每个新连接,fork
一个要阻塞的子进程,写如下:
//pseudo-code
int bytes_from_client;
while(true)
if( (bytes_from_client = recv(xx,xx,xx,xx)) <= 0 )
if(bytes_from_client == 0)
client_shutdown();
else
error_handle();
else
//recv data from client and send messages to all the other clients
for(int i = 0; i < all_sockets[x]; i++)
send(xx,xx,xx,xx);
好的,那么我需要处理一些全局变量的同步问题。使用mutex
或其他东西。 (困难的部分)
现在开始提问:
与我稍后描述的多线程相比,我从poll
设计模式中究竟有什么好处?不需要处理同步?只有这1个优势?
(一个更通用但更有意义的问题)poll
制作的这种设计模式是否像函数(select
、epoll
)一样让它们如此不同/独特和伟大? (我是新手,之所以问这个,是因为我看到很多人说poll
家族功能有多么伟大和重要。但他们从不说明原因,也没有给出例子或比较。)
【问题讨论】:
【参考方案1】:一个简单的select()
循环运行良好的一个基本原因是网络数据包总是一次一个到达,并且与任何 CPU 的惊人速度相比,速度非常慢。更复杂的安排根本没有任何优势。
通常,一个线程或进程专门用于处理网络连接...轮询传入数据包并代表每个人发送传出消息。 (我听说它被称为“电报员”。)然后它使用队列将工作分配给稳定的“工蜂”进程,这些进程在一个队列上检索请求,然后将传出的答案发布到另一个队列,该队列也是被电报员收听。
有时,电报员只是侦听连接请求,将句柄放在队列中,然后工蜂打开连接并自己进行联网。但是,再一次,他们可以简单地使用轮询,它工作得很好。即使是最快的通信线路也比 CPU 慢几个数量级。
【讨论】:
我真的很喜欢 epoll 或 select 用于一些网络服务器用例。但我不会说网络数据包到达缓慢,尤其是在现代 10 GBit 甚至 100 GBit NIC 上。一个极端的例子是用户空间网络,例如 Intel DPDK。接收循环中的一次缓存未命中将破坏性能。以上是关于鉴于这个例子,与使用多个线程或进程相比,我从轮询设计中得到啥好处?的主要内容,如果未能解决你的问题,请参考以下文章