【问题标题】:How to simplify multithreaded design using asio?如何使用 asio 简化多线程设计?
【发布时间】:2014-02-20 09:48:31
【问题描述】:

这是一个很长的问题。 TL;DR:我不知道如何使用 asio 正确设计程序。

人们已经为 CLI 实用程序编写了 GUI 包装器。我正在为这样一个实用程序编写一个“代理”,它将 GUI 发出的命令中继到远程计算机上运行的实用程序的另一个副本(通过远程计算机上的另一个“代理”)。

我目前正在使用 asio 进行套接字 I/O,但我在 main() 中使用一个简单的循环来执行来自 stdin 的阻塞读取(在 stdin 和 Windows 上的朋友中无法进行异步 I/O)。我试图通过使用简单的发布/订阅机制来解耦一切。消息订阅者在自己的线程上运行,并通过std::condition_variable 接收来自std::deque 的消息。我目前有以下 I/O 相关的类:

  • SocketServer:在自己的线程上运行,创建asio::io_service,绑定并监听端口,并接受远程连接。
  • SocketClient: 创建一个asio::io_service,连接到远程主机并提供​​密码。
  • SocketConnection: 由 SocketServer 或 SocketClient 创建。验证远程主机(仅限服务器),从套接字读取,并在接收到SocketOutputMessage 时写入套接字(在单独的线程上)。
  • ConsoleWriter:在自己的线程上运行,在收到ConsoleOutputMessage 时写入stdout

对我来说,这种设计的主要缺陷是线程太多! SocketServer 需要自己的线程,因为阻塞了对asio::io_service::run() 的调用。同样,ConsoleWriter 在自己的线程上,以确保对stdout 的所有写入都发生在同一个线程上。我不想要另一个用于 SocketConnection 的线程,但由于 pub/sub 需要它。 (我希望消息总是在 receiver's 线程上发送)

请有人向我提供有关如何简化上述设计的建议(并希望减少所需的线程数)?为此,我应该了解哪些 asio 功能?如果可以,请提供一些示例代码和/或相关网站的链接或 SO 答案。

干杯。

【问题讨论】:

    标签: c++ multithreading sockets boost-asio


    【解决方案1】:

    我建议您创建两个 io_services,第一个(您可以在线程中调度)应该用于所有套接字通信。)第二个(在主线程上调度)应该处理控制台活动。

    例如:

    main()
    {
      // Run the network service
      std::thread service([]() { net_service.run(); });
      // Now run the console service
      console_service.run();
    }
    

    要在两个服务之间进行通信,请使用io_service::post() 操作。这会将处理程序发布到在该上下文中执行的给定 io 服务上。例如。

    client_socket.async_read_some(_data, [](...) {
      // Now you have the data and you want to print it..
      console_service.post([=]() { std::cout << "message " << _data << std::endl; });
    });
    

    所以现在当您从client_socket 中读取某些内容时,您将该数据发布到控制台服务 - 请注意,复制数据或者如果您想避免复制,请创建一些单独的队列,就像您拥有的那样,并且只需使用post() 机制通知其他io_service。

    注意:另一个答案提到poll(),这将导致上下文旋转,因为如果没有要完成的内容,它将立即返回。

    【讨论】:

      【解决方案2】:

      io_serivce.poll() 只是运行当前事件然后返回,我重复调用它而不是为此设置一个线程。

      您可以通过某种形式的锁/互斥锁/自旋锁/...锁定写入部分来避免在其自己的线程上使用控制台编写器。

      如果您使用 async_read() 而不是 read() ,您将提供一个回调,只要有要读取的数据就会被调用。这样你就可以让 asio 处理线程,你就不用担心了。

      【讨论】:

        猜你喜欢
        • 2011-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多