io_service类

你应该已经发现大部分使用Boost.Asio编写的代码都会使用几个io_service的实例。io_service是这个库里面
最重要的类;它负责和操作系统打交道,等待所有异步操作的结束,然后为每一个异步操作调用其完成处
理程序。
如果你选择用同步的方式来创建你的应用,你则不需要考虑我将在这一节向你展示的东西。 你有多种不同
的方式来使用io_service。在下面的例子中,我们有3个异步操作,2个socket连接操作和一个计时器等待操
作:
有一个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(5));
t.async_wait(timeout_handler);
service.run();
有一个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(5));
t.async_wait(timeout_handler);
for ( int i = 0; i < 5; ++i)
boost::thread( run_service);
void run_service()
{
service.run();
}
有多个io_service实例和多个处理线程的多线程例子:
io_service service[2];
ip::tcp::socket sock1(service[0]);
ip::tcp::socket sock2(service[1]);
sock1.asyncconnect( ep, connect_handler);
sock2.async_connect( ep, connect_handler);
deadline_timer t(service[0], boost::posixtime::seconds(5));
t.async_wait(timeout_handler);
for ( int i = 0; i < 2; ++i)
boost::thread( boost::bind(run_service, i));

void run_service(int idx)
{
service[idx].run();
}
首先,要注意你不能拥有多个io_service实例却只有一个线程。下面的代码片段没有任何意义:
for ( int i = 0; i < 2; ++i)
service[i].run();
上面的代码片段没有意义是因为service[1].run()需要service[0].run()先结束。因此,所有由service[1]处理的
异步操作都需要等待,这显然不是一个好主意。
在前面的3个方案中,我们在等待3个异步操作结束。为了解释它们之间的不同点,我们假设:过一会操作1
完成,然后接着操作2完成。同时我们假设每一个完成处理程序需要1秒钟来完成执行。
在第一个例子中,我们在一个线程中等待三个操作全部完成,第1个操作一完成,我们就调用它的完成处理
程序。尽管操作2紧接着完成了,但是操作2的完成处理程序需要在1秒钟后,也就是操作1的完成处理程序
完成时才会被调用。
第二个例子,我们在两个线程中等待3个异步操作结束。当操作1完成时,我们在第1个线程中调用它的完成
处理程序。当操作2完成时,紧接着,我们就在第2个线程中调用它的完成处理程序(当线程1在忙着响应操
作1的处理程序时,线程2空闲着并且可以回应任何新进来的操作)。
在第三个例子中,因为操作1是sock1的connect,操作2是sock2的connect,所以应用程序会表现得像第二
个例子一样。线程1会处理sock1 connect操作的完成处理程序,线程2会处理sock2的connect操作的完成处
理程序。然而,如果sock1的connect操作是操作1,deadline_timer t的超时操作是操作2,线程1会结束正
在处理的sock1 connect操作的完成处理程序。因而,deadline_timer t的超时操作必须等sock1 connect操
作的完成处理程序结束(等待1秒钟),因为线程1要处理sock1的连接处理程序和t的超时处理程序。

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

boost asio中io_service类的几种使用的更多相关文章

  1. boost.asio系列——io_service

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

  2. Java中匿名类的两种实现方式(转)

    使用匿名内部类课使代码更加简洁.紧凑,模块化程度更高.内部类能够访问外部内的一切成员变量和方法,包括私有的,而实现接口或继承类做不到.然而这个不是我说的重点,我说的很简单,就是匿名内部类的两种实现方式 ...

  3. Yii中实例化类的四种方式

    1.最简单的也是最基本的,大家都会的一种 use yii\caching\FileCache; $cache = new FileCache(); $cache->set("name& ...

  4. C++面试中string类的一种正确写法

    C++ 的一个常见面试题是让你实现一个 String 类,限于时间,不可能要求具备 std::string 的功能,但至少要求能正确管理资源.具体来说: 能像 int 类型那样定义变量,并且支持赋值. ...

  5. Struts2中Action类的三种写法

      一.普通的POJO类(没有继承没有实现)-基本不使用 POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans,是为了避免和EJB混淆所创 ...

  6. 3.Struts2中Action类的三种写法

    一.普通的POJO类(没有继承没有实现)-基本不使用 public class DemoAction1 { public String execute(){ System.out.println(&q ...

  7. C++面试中string类的一种正确简明的写法

    本文首发于酷壳网 http://coolshell.cn/articles/10478.html 先说说程序员(应届生)面试的一般过程,一轮面试(面对一到两个面试官)一般是四.五十分钟,面试官会问两三 ...

  8. BOOST.Asio——Overview

    =================================版权声明================================= 版权声明:原创文章 谢绝转载  啥说的,鄙视那些无视版权随 ...

  9. boost::asio译文

        Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENS ...

随机推荐

  1. GPL 与 LGPL 扫盲

    本文部分摘自评论:从射手QQ之争看开源许可证的选择 首先,开源并不代表放弃自身的权力,相反,开源软件之所以存在,正是它非常注重这种权力,并且把这种权力赋予了软件的所有使用者.小心的选择许可证是开发开 ...

  2. MySQL查看和修改字符集的方法

    一.查看字符集 1.查看MYSQL数据库服务器和数据库字符集 方法一:show variables like '%character%';方法二:show variables like 'collat ...

  3. python微信库 --- itchat

    python实现微信接口——itchat模块 安装 pip install itchat 登录 itchat.auto_login() # 这种方法将会通过微信扫描二维码登录,但是这种登录的方式确实短 ...

  4. java程序实现Unicode码和中文互相转换

      根据前一篇的补充问题http://blog.csdn.net/fancylovejava/article/details/10142391 有了前一篇文章的了解,大概了解了unicode编码格式了 ...

  5. c的详细学习(11)文件

    为了提高数据输入/输出的处理效率,可以将程序运行时所需要的原始数据从文件中读取,并将程序运行的结果写入到文件中.     (1)文件概述     1)基本概念 文件是指存储在外部介质上数据的集合,可以 ...

  6. Html标签使用——文字、列表、表格、超链接

    注:文章来源于传智播客毕向东老师使用课件和网络.整理学习如下: 一.Html内容 1.   Html就是超文本标记语言的简写,是最基础的网页语言. 2.   Html是通过标签来定义的语言,代码都是由 ...

  7. 【leetcode刷题笔记】Evaluate Reverse Polish Notation

    Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, ...

  8. img标签中alt属性与title属性

    alt属性 1.alt属性是考虑到不支持图像显示或者图像显示被关闭的浏览器的用户,以及视觉障碍的用户和使用屏幕阅读器的用户.当图片不显示的时候,图片的替换文字.2.alt属性值得长度必须少于100个英 ...

  9. 多种方法求java求整数的位数

    方法一 private static int getNumLenght(long num){ num = num>0?num:-num; return String.valueOf(num).l ...

  10. 织梦dedecms 扩展channel栏目标签 获取交叉栏目名称和链接

    channel栏目标签默认有调用顶级栏目(top).子栏目(son).同级栏目(self),那想获取交叉栏目的名称和链接怎么获取呢? 其实在原来的代码上改一下就可以了.下面是具体代码.打开文件chan ...