c++ - 鉴于此示例,与使用多线程或进程相比,轮询设计对我有何好处?

标签 c++ c multithreading sockets multiprocessing

最近一直在学习socket编程,终于在Beej's Guide to Network Programming找到了一些很好的例子.

poll section 下有一个使用poll 的聊天服务器示例.

代码:

charsever.c (聊天服务器接收客户端消息并向所有其他客户端发送消息)


逐行阅读代码并完全理解示例后,我突然意识到设计的巧妙和整洁。

基本上,它使用轮询 来监视所有内容,服务器监听套接字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 或其他东西。 (困难部分)

现在开始提问:

  1. 与我稍后描述的多线程模式相比,poll 设计模式到底有什么好处?不需要处理同步?只有这1个优势?

  2. (一个更通用但有意义的问题)这种设计模式是由 poll 制作的,类似函数(selectepoll)让他们如此不同/独特和伟大? (我是新手所以问这个是因为看到很多人说poll家族的函数有多么伟大和重要。但是他们从来不说为什么,也不举例,也不比较。)

最佳答案

一个简单的 select() 循环如此有效的一个基本原因是网络数据包总是一次一个地到达,与任何 CPU 的致盲速度相比,它非常慢.更复杂的安排根本没有任何优势。

通常,一个线程或进程专用于处理网络连接……轮询传入数据包并代表每个人发送传出消息。 (我听说它被称为“电报员”。)然后它使用队列将工作分配给稳定的“工蜂”进程,这些进程在一个队列上检索请求,然后将传出的答案发布到另一个队列,该队列也是被电报员收听了。

有时,电报员只是简单地监听连接请求,将句柄放在队列中,然后工蜂打开连接并自己进行网络连接。但是,再一次,他们可以简单地使用轮询,而且效果很好。即使是最快的通信线路也比 CPU 慢几个数量级。

关于c++ - 鉴于此示例,与使用多线程或进程相比,轮询设计对我有何好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58878749/

相关文章:

c++ - 如何在 C++ 中使用 sort() 函数一起做某事?

c++ - OpenGL glUniform1ui() 抛出 GLError GL_INVALID_OPERATION

c - 将 uint8_t 可移植重新解释为 int8_t 并强制补码

python - Python中混合多处理和线程的现状

c++ - Winrt/XAML/C++ : Get Color from String Value

C++初始化数组存储大小

c - 实现各种大小的结构的基于数组的内存池

无法将 char 数组分配给我的结构数组的第三个槽

java - 运行多个线程(每个线程都有自己的应用程序上下文)并正常关闭

java - 字节数组多线程读写