【问题标题】:Why do we need io_service in boost?为什么我们在 boost 中需要 io_service?
【发布时间】:2016-09-17 18:25:58
【问题描述】:

我正在尝试学习 Boost.asio 库。 现在我可以创建一个可以通信的客户端和服务器了。

为什么我们需要定义一个 io_service 对象?因为如果这是唯一可用于套接字注册/与底层操作系统通信的对象类型,我们为什么还要定义它。插座不能自动猜到吗?我在这里错过了什么?

【问题讨论】:

    标签: c++ networking boost boost-asio


    【解决方案1】:

    你是否在反向发现单身人士为什么不好?这就是你的答案。

    完成后,可以控制并决定在 Asio 中的服务之间共享多少资源。

    因此,您现在可以

    • 在您的应用程序中使用 Asio,即使您链接到的库之一也使用它
    • 将 Asio 用于每个线程一个服务(因此不会有共享状态)或每个服务有多个线程

    等等

    【讨论】:

      【解决方案2】:

      boost::asio::io_service 是任何与 asio 相关的应用程序的核心部分,有两个角色:

      1. 这是一个函数对象的队列。你甚至可以在像这样的非网络相关软件中使用它:

        void func1() { //做一点事 } 无效 func2(int x) { // 使用 x 做其他事情 }

        int main() { boost::asio::io_service io; io.post(func1); io.post(boost::bind(func2, 123)); io.run(); }

      此代码示例将在您调用 io.run() 时按顺序执行这两个函数 - 而不是在发布期间。发布到 io_service 只是一个 enque 操作。 您可能想知道为什么这会很有用。答案是,在这个简单的例子中显然不是。但是,如果您认为同一 io_service 实例的方法 run() 可以由两个或多个线程同时调用,那么您最终会得到一个模型,其中多个线程可以充当其他线程生成的工作项的工作人员。这是一个非常强大的想法,可以促进多线程。

      1. 这是一个选择循环:在网络应用程序中,您可能需要处理大量表示套接字的文件描述符。传统上,这是在一个或多或少看起来像这样的 while 循环中完成的: 而(!完成){ // 检查哪些文件描述符是可读或可写的 - 这是通过 poll()、select() 等完成的 // 对于每个可读的文件描述符:读入一些缓冲区并处理接收到的字节 // 对于每个可写文件描述符:为该描述符写入任何挂起的字节 - 如果有的话。 }

      所以,每次你调用类似:

      boost::asio::async_read(my_asio_socket, my_buffer, boost::bind(my_callback,...))
      

      真正会发生的是底层描述符将通过 select() 机制进行可读性测试。当描述符变得可读时,数据将存储在 my_buffer 中,当缓冲区满时,通过 bind(...) 构造的函数对象将插入 io_service 的函数对象队列中。因此,正在执行 my_io_service.run() 的线程将被唤醒并执行此回调。

      请注意,多个线程不是强制性的。您仍然可以像第一个示例一样使用主线程。如果您以这种方式设计应用程序,只是 io_service 可以方便地将负载分派到多个线程。

      希望这会有所帮助。

      【讨论】:

      • 不是select 阻塞吗?我希望async_read 使用poll 的某种组合
      • 选择未阻塞:int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout );。此外,kqueue、epoll、poll、IO Completion Ports、select 或任何使用的都是实现细节。
      • 之前的评论不正确。选择和类似的功能会阻塞,直到可以读取或写入某些描述符或最长的时间(实际上您可以使用它来实现计时器)。传统的基于选择的应用程序只会在没有任何事情要做时调用 select,因此可以阻塞直到经过一段时间或直到收到某些内容。在 asio 情况下, async_read 不会自行触发 select。这是通过 io_service::run (阻塞)完成的。我希望 async_read 仅在某种集合中插入一个描述符,该描述符将在下一次 select() 调用期间进行检查。
      猜你喜欢
      • 2013-06-13
      • 2019-06-09
      • 2014-06-18
      • 2017-02-26
      • 2011-04-03
      • 2017-07-27
      • 2020-09-21
      • 2020-03-09
      相关资源
      最近更新 更多