大部分使用Boost.Asio编写的代码都会使用几个io_service的实例。io_service是这个库里面最重要的类;它负责和操作系统打交道,等待所有异步操作的结束,然后为每一个异步操作调用其完成处理程序。

你有多种不同的方式来使用io_service。在下面的3个例子中,我们有3个异步操作,2个socket连接操作和一个计时器等待操作。为了解释它们之间的不同点,我们假设:过一会操作1完成,然后接着操作2完成。同时我们假设每一个完成处理程序需要1秒钟来完成执行。

一个io_service实例和一个处理线程的单线程:

io_service service; // 所有socket操作都由service来处理
ip::tcp::socket sock1(service); // all the socket operations are handled by service
ip::tcp::socket sock2(service);
sock1.asyncconnect( ep, connect_handler);
sock2.async_connect( ep, connect_handler);
deadline_timer t(service, boost::posixtime::seconds());
t.async_wait(timeout_handler);
service.run();

我们在一个线程中等待三个操作全部完成,第1个操作一完成,我们就调用它的完成处理程序。尽管操作2紧接着完成了,但是操作2的完成处理程序需要在1秒钟后,也就是操作1的完成处理程序完成时才会被调用。

一个io_service实例和多个处理线程的多线程:

io_service service;
ip::tcp::socket sock1(service);
ip::tcp::socket sock2(service);
sock1.asyncconnect( ep, connect_handler);
sock2.async_connect( ep, connect_handler);
deadline_timer t(service, boost::posixtime::seconds());
t.async_wait(timeout_handler);
for ( int i = ; i < ; ++i)
boost::thread( run_service);
void run_service()
{
service.run();
}

我们在两个线程中等待3个异步操作结束。当操作1完成时,我们在第1个线程中调用它的完成处理程序。当操作2完成时,紧接着,我们就在第2个线程中调用它的完成处理程序(当线程1在忙着响应操作1的处理程序时,线程2空闲着并且可以回应任何新进来的操作)。

多个io_service实例和多个处理线程的多线程:

io_service service[];
ip::tcp::socket sock1(service[]);
ip::tcp::socket sock2(service[]);
sock1.asyncconnect( ep, connect_handler);
sock2.async_connect( ep, connect_handler);
deadline_timer t(service[], boost::posixtime::seconds());
t.async_wait(timeout_handler);
for ( int i = ; i < ; ++i)
boost::thread( boost::bind(run_service, i));
void run_service(int idx)
{
service[idx].run();
}

因为操作1是sock1connect,操作2是sock2connect,所以应用程序会表现得像第二个例子一样。线程1会处理sock1 connect操作的完成处理程序,线程2会处理sock2connect操作的完成处理程序。然而,如果sock1connect操作是操作1,deadline_timer t的超时操作是操作2,线程1会结束正在处理的sock1 connect操作的完成处理程序。因而,deadline_timer t的超时操作必须等sock1 connect操作的完成处理程序结束(等待1秒钟),因为线程1要处理sock1的连接处理程序和t的超时处理程序。

注意不能拥有多个io_service实例却只有一个线程。下面的代码片段没有任何意义:

for ( int i = ; i < ; ++i)
service[i].run();

因为service[1].run()需要service[0].run()先结束。因此,所有由service[1]处理的异步操作都需要等待,这显然不是一个好主意。

下面是需要从前面的例子中学到的:

  • 第一种情况是非常基础的应用程序。因为是串行的方式,所以当几个处理程序需要被同时调用时,你通常会遇到瓶颈。如果一个处理程序需要花费很长的时间来执行,所有随后的处理程序都不得不等待。
  • 第二种情况是比较适用的应用程序。他是非常强壮的——如果几个处理程序被同时调用了(这是有可能的),它们会在各自的线程里面被调用。唯一的瓶颈就是所有的处理线程都很忙的同时又有新的处理程序被调用。然而,这是有快速的解决方式的,增加处理线程的数目即可。
  • 第三种情况是最复杂和最难理解的。你只有在第二种情况不能满足需求时才使用它。这种情况一般就是当你有成千上万实时(socket)连接时。你可以认为每一个处理线程(运行io_service::run()的线程)有它自己的select/epoll循环;它等待任意一个socket连接,然后等待一个读写操作,当它发现这种操作时,就执行。大部分情况下,你不需要担心什么,唯一你需要担心的就是当你监控的socket数目以指数级的方式增长时(超过1000个的socket)。在那种情况下,有多个select/epoll循环会增加应用的响应时间。

boost::asio::io_service类的更多相关文章

  1. boost asio io_service学习笔记

    构造函数 构造函数的主要动作就是调用CreateIoCompletionPort创建了一个初始iocp. Dispatch和post的区别 Post一定是PostQueuedCompletionSta ...

  2. boost::asio::io_service::定时器任务队列

    使用io_service和定时器写的一个同步和异步方式的任务队列 #pragma once #include <string> #include <iostream> #inc ...

  3. 概念理解:boost::asio::io_service

    IO模型 io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象). asio::io_service i ...

  4. boost::asio::io_context类

    //有个疑惑: 向io_context对象中提交的任务只能被顺序化的执行. //下面这个构造函数表明可以运行多线程啊..... /** * Construct with a hint about th ...

  5. Boost::asio io_service 实现分析

    io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数.Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run ...

  6. boost asio 学习(一)io_service的基础

    原文  http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio/ 编译环境 b ...

  7. boost.asio系列——io_service

    IO模型 io_service对象是asio框架中的调度器,所有异步io事件都是通过它来分发处理的(io对象的构造函数中都需要传入一个io_service对象). asio::io_service i ...

  8. boost asio tcp server 拆分

    从官方给出的示例中对于 boost::asio::ip::tcp::acceptor 类的使用,是直接使用构造函数进行构造对象,这一种方法用来学习是一个不错的方式. 但是要用它来做项目却是不能够满足我 ...

  9. boost.asio源码剖析(五) ---- 泛型与面向对象的完美结合

    有人说C++是带类的C:有人说C++是面向对象编程语言:有人说C++是面向过程与面向对象结合的语言.类似的评论网上有很多,虽然正确,却片面,是断章取义之言. C++是实践的产物,C++并没有为了成为某 ...

随机推荐

  1. 利用Cocoapods创建基于SVN的私有库podspec

    由于项目年后要进行组件化,考虑到公司内部实现的一些私有组件,不对外公开,而又想在不同项目中使用,该怎么办呢?由于cocoapods有了强大的功能,可以自己创建podspec,更可以设置私有的库.那么利 ...

  2. 【探路者】final贡献分配

     [探路者]组成员及各位博客地址. 1蔺依铭:http://www.cnblogs.com/linym762/ 2张恩聚:http://www.cnblogs.com/zej87/ 3米赫:http: ...

  3. “Hello World!”团队第六周第六次会议

    “Hello World!”团队第六周第六次会议   博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七.燃尽图 八.checkout& ...

  4. OO第四次作业-对前三次作业总结

    第一次作业由于直接没怎么学过java,全靠一星期速成,前几天看了java的语法,但是因为光看没有打代码,学习效果并不是特别好.由面向过程转向面向对象,不是特别清楚该怎么办,虽然写的是两个类,但实际上是 ...

  5. 【CSAPP笔记】10. 代码优化

    写程序的主要目标是使它在所有可能的情况下都能正确运行(bug free),一个运行得很快但有 bug 的程序是毫无用处的.在 bug free 的基础上,程序员必须写出清晰简洁的代码,这样做是为了今后 ...

  6. 浅谈Java中的Hashmap

    HashMap:   java.lang.Object ∟ java.util.AbstractMap<K,V> ∟ java.util.HashMap<K,V> 类型参数: ...

  7. 使用GatewayWorker 开发个即时聊天demo

    前言: 上手册以示尊重:https://www.kancloud.cn/walkor/gateway-worker/326138: https://www.cnblogs.com/fuqiang88/ ...

  8. (一)Jmeter 简单的录制

    JMeter介绍 1.JMeter,一个100%的纯Java桌面应用,它是Apache组织的开放源代码项目,它是功能和性能测试的工具.JMeter可以用于测试静态或者动态资源的性能(文件.Servle ...

  9. dedecms 织梦本地调试 后台反映非常慢的处理办法

    最近需要做几个企业站,所以呢,考虑了一下,没有用phpcms,而选择了 织梦.毕竟么,织梦用来做企业站还是比较合适的.好了,进正题: 在本地调试的时候,会非常的卡顿.调试的方法如下: 安装目录/dat ...

  10. QT源码解析(七)Qt创建窗体的过程,作者“ tingsking18 ”(真正的创建QPushButton是在show()方法中,show()方法又调用了setVisible方法)

    前言:分析Qt的代码也有一段时间了,以前在进行QT源码解析的时候总是使用ue,一个函数名在QTDIR/src目录下反复的查找,然后分析函数之间的调用关系,效率实在是太低了,最近总结出一个更简便的方法, ...