boost.asio学习笔记03——io objects

71 篇文章 3 订阅
9 篇文章 0 订阅

http://blog.163.com/henan_lujun/blog/static/19538333201341452720625/

boost.asio学习笔记03——io objects  

asio的文档,告诉我们在声明一个io_service对象之后,就可以创建io对象去干活了,例如:

int main(int argc, char* argv[])

{

    boost::asio::io_service io_service;

 

    tcp::resolver resolver(io_service);

    tcp::resolver::query query("www.boost.org""80");

    tcp::resolver::iterator iterator = resolver.resolve(query);

 

 

上图中main()的第二行代码声明了一个tcp::resolver对象,后续进行地址解析的逻辑,都是围绕此resolver对象展开的。那么这个resolver是一个什么样的类型呢?阅读源代码我们在boost::asio::ip::tcp类内部看到了这样的类型别名定义:

    

typedef basic_resolver<tcp> resolver;

 

是否似曾相识呢? 是的,这和我们STL中的string, iostream等一样,使用的都是某个模板类的一个实例。这里的resolverbasic_resolvertcp模版参数下的实例,stringbasic_stringchar模版参数下的实例——boost库和STL库统一风格的一个体现。

 

asio大量采用这种技术,所有和resolver一样提供io功能的类,都是某个baisc_模版类的实例化。下面我们来研究一下asioio object逻辑。

 

io object 类关系网

继续向上追溯basic_resolver,知道该类从basic_io_object派生,主要负责地址解析相关的操作,提供的主要接口有resolver(), async_resolve()等。

 

查看整个asio的源代码,我们发现从basic_io_object派生的类不少,他们分别负责一些具体的事务,例如basic_socket_acceptor可以作为一个服务器进行侦听,提供了诸如bind(), listen()等接口;再如basic_socket类是对socket IO 操作的封装,提供了receive(), async_receive(), read_some(), async_readsome(), write_some(), async_write_some()等接口。

 

整个asio中的io object关系网,我们用下图来显示:

 

boost.asio学习笔记03——io objects - 地线 - 别再让虚假消息充斥这本已混乱的世界

 

这些io object的功能,简述如下:

  • basic_deadline_timer 提供定时器功能,可以同步等待,也可以异步等待。
  • basic_waitable_timer basic_deadline_timer具有同样的功能,主要区别为该定时器可以和C++ 11中引入的chrono库协作。
  • basic_signal_set 支持信号相关的操作,异步方式等待单个或者多个信号的发生。
  • basic_socket_acceptor 作为服务器进行侦听,接收连接请求。
  • basic_serial_port 对串口操作进行支持。
  • basic_resolver 地址解析类。
  • basic_stream_socket 提供同步、异步方式的基于流的socket操作。
  • basic_datagram_socket 提供同步、异步方式的基于数据报文的socket操作。
  • basic_raw_socket提供同步、异步方式的基于raw数据的socket操作
  • basic_seq_packet_socket提供同步、异步方式的基于有序包的socket操作
  • basic_socket_streambuf ?
  • basic_object_handle windows handle的封装,可以以异步或者同步方式等待
  • basic_random_access_handlewindows 可随机访问的handle的封装,可以以异步或者同步方式等待
  • basic_stream_handlewindows面向流handle的封装,可以以异步或者同步方式等待
  • basic_descriptor POSIX描述符进行封装。

 

另外一点,所有这些io object的构造函数,都要求有一个io_service& 作为参数,使用这一参数,这些io_object对象知道了自己的归属,之后自己所要派发出去的同步、异步操作请求,都将通过自己所在的这个io_service对象来完成。这也就说明了,为什么创建io_service对象是整个asio程序的第一步。

 

io object服务委托

上述的这些io object类,提供了应用开发中常用的各种“实际”功能,例如地址解析,以及socket读写等,那么这些io object类和第一部分中的service类之间存在着什么样的关系呢? 会不会是这些io object只是一个应用的接口,而具体的功能则委托给service类来完成呢? 如果是这样的,那么又是如何实现的呢?

 

带着这些问题,我们继续研究resolver类的源代码,看看他所提供的功能,到底是如何实现的。

resolver是如何委托的

我们知道,resolver类是在boost::asio::ip::tcp类中的一个类型别名:

 

     typedef basic_resolver<tcp> resolver;

 

那么,resolver类所提供的async_resolve()接口,就来自于basic_resolver类。再来看看basic_resolver::async_resolve()的实现——该函数有两个重载,我们以其中一个为例:

  template <typename ResolveHandler>

  void async_resolve(const queryqBOOST_ASIO_MOVE_ARG(ResolveHandler) handler)

  {

    // If you get an error on the following line it means that your handler does

    // not meet the documented type requirements for a ResolveHandler.

    BOOST_ASIO_RESOLVE_HANDLER_CHECK(

        ResolveHandler, handler, iterator) type_check;

 

    return this->service.async_resolve(this->implementation, q,

        BOOST_ASIO_MOVE_CAST(ResolveHandler)(handler));

  }

 

可见,async_resolve()果然是委托给了某个service类来做事的——再一次,典型的有事儿秘书干。那么,这儿的“this->service 又是什么呢?

 

通过跟踪代码的执行,知道该service其实是第一部分曾经提到过的boost::asio::ip::resolver_service,而它又委托给了boost::asio::detail::resolver_service——这家伙再无其他可以委托的对象了,只有苦逼的自己做事儿了——其基本思路就是先创建一个用以地址解析的resolve_op,用这个op来代表本次异步操作,之后启动op去做事情。至于op又是什么东西,稍后在operation部分做介绍;先贴出这段苦主:

  // boost::asio::detail::resolver_service

  template <typename Handler>

  void  async_resolve(implementation_typeimpl,

                      const query_typequeryHandler handler)

  {

    // Allocate and construct an operation to wrap the handler.

    typedef resolve_op<ProtocolHandlerop;

    typename op::ptr p = { boost::addressof(handler),

      boost_asio_handler_alloc_helpers::allocate(

        sizeof(op), handler), 0 };

    p.p = new (p.v) op(implquery, io_service_impl_, handler);

 

    BOOST_ASIO_HANDLER_CREATION((p.p, "resolver", &impl, "async_resolve"));

 

    start_resolve_op(p.p);

    p.v = p.p = 0;

  }

PS

-   做过Symbian开发的对这种形式似曾相识,这多少和Active Object异曲同工

-   那几行创建op的代码还不是很明白

 

OK,至此,整个async_resolve()从上到下就拉通了。概括起来,就是io object将具体功能委托给服务类,服务类又委托给和平台实现相关的服务类来完成最后的功能。

io_object的服务创建

通过resolver的执行,我们知道了其层层委托关系,那么resolver所委托的this->service又是怎么来的呢?下面部分,我们来分析io_object所做的服务管理工作。

 

首先来看该service的具体类型。

 

要想知道service是如何创建的,我们就要追根朔源找到resolver的具体类型声明,看看到底是如何将service拉上贼船的。好吧,我们再次从头开始(别嫌啰嗦):

 

typedef basic_resolver<tcp> resolver;

 

针对这个模版实例,将basic_resolver展开:

 

template <typename InternetProtocol,

         typename ResolverService = resolver_service<InternetProtocol> >

class basic_resolver: public basic_io_object<ResolverService>

à

template <tcp,

         typename ResolverService = resolver_service<tcp> >

class basic_resolver: public basic_io_object< resolver_service<tcp> >

 

再对basic_io_object进行展开:

template <typename IoObjectService>

class basic_io_object

à

template < resolver_service<tcp> >

class basic_io_object

 

basic_io_object内部展开:

typedef IoObjectService service_type;

à

typedef resolver_service<tcp> service_type;

 

于是,可以确定basic_io_object::service的类型为resolver_service<tcp>&从而将io object和下层的service关联起来。

 

再来看basic_io_object::service的初始化。我们来看其构造函数:

  explicit basic_io_object(boost::asio::io_serviceio_service)

    : service(boost::asio::use_service<IoObjectService>(io_service))

  {

    service.construct(implementation);

  }

 

很明显,在构造过程中,使用use_service的返回值来初始化该service成员;我们知道,use_service会在io_service所维护的service链表中查找该类型,如果没有,就创建一个新的service实例;在此,就可以确保resolve_service<tcp>的实例已经被创建出来了,该服务就可以工作了(当然,不要忘记,该service事实上又委托了一层,而这个最底层的service实例,在此resolve_service<tcp>的构建过程中,内部再次调用use_service()创建出来了。过程如下:

boost.asio学习笔记03——io objects - 地线 - 别再让虚假消息充斥这本已混乱的世界

  

除此之外,在构造函数体中,调用了serviceconstruct函数,做进一步的初始化。(PS:是否有Symbian中的二段构造的影子呢?)

asio io逻辑总结

前面部分以resolver为例,分析了resolver的功能和对应service之间的关系,纵观所有的io object,都是采用了这种模式,总结起来有如下几点:

·           asio提供了多个basic_ 模版类。

·           应用层使用对应的basic_ 模版类的typedef的具体类,对外提供服务接口。

·           io object内部,将操作委托给底层服务类。

·           底层服务类再次将操作委托给平台实现层,完成实际的工作。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
icoFoam 求解器名称 |-createFields.H 场变量的声明和初始化 ————————————————————————————————————————————— Info<< "Reading transportProperties\n" << endl; //屏幕提示读入参数控制文件,等价于 C++中std::cout //声明属性字典类对象,该对象由 constant 文件夹下的“transportProperties”初始化创建。 IOdictionary transportProperties ( IOobject //其实IOobject,顾名思义就是输入输出对象,它完成的是一个桥梁的作用,即连接要构造的类及硬盘中的相应文件。这可以通过其成员函数objectStream()了解到,当完成了“搭桥”之后,便可通过这一成员函数返回硬盘文件对应的输入流,从而从输入流中读入将要构造的类的相关信息// ( "transportProperties", // 文件名称 runTime.constant(), // 文件位置,case/constant mesh, // 网格对象 IOobject::MUST_READ_IF_MODIFIED, //如果更改,必须读入 IOobject::NO_WRITE // 不对该文件进行写操作 ) ); //字典查询黏性,以便初始化带有单位的标量 dimensionedScalar nu ( transportProperties.lookup("nu") ); //屏幕提示创建压力场 Info<< "Reading field p\n" << endl; //创建压力场 volScalarField p //声明一个带单位的标量场,网格中心存储变量。 ( IOobject // IOobject主要从事输入输出控制 ( "p", // 压力场初始文件名称 runTime.timeName(), // 文件位置,由case中的system/controlDict中的startTime控制 //
Boost.Asio是一种功能强大的C++网络编程库,其中包含了HTTP Server框架。学习Boost.Asio的HTTP Server模块可以帮助我们了解如何使用C++编写一个高效且稳定的HTTP服务器。 开始学习Boost.Asio的HTTP Server模块之前,我们首先需要了解HTTP协议的基本知识。HTTP协议是一种用于客户端和服务器之间进行通信的协议,我们在这个基础上构建HTTP服务器。然后,我们需要了解Boost.Asio库的基本概念和用法,比如异步操作、套接字和流等。 在学习Boost.Asio的HTTP Server模块时,我们需要了解以下几个方面: 1. 创建一个TCP服务器:我们需要使用Boost.Asio库提供的TCP套接字来创建一个服务器,监听指定的端口,并能够处理来自客户端的连接请求。 2. 解析HTTP请求:服务器接收到客户端发送的请求后,需要解析HTTP报文,将请求方法、路径和其他相关信息提取出来,以便后续处理。 3. 处理HTTP请求:服务器根据解析出的请求信息,执行相应的处理逻辑,并生成HTTP响应报文,然后通过TCP连接将响应发送给客户端。 4. 异步操作管理:Boost.Asio库的一个重要特性是提供了非阻塞的异步操作。我们需要了解如何使用异步操作来实现高性能的HTTP服务器,如异步读取请求、异步处理请求和异步发送响应等。 5. 错误处理和异常处理:在编写网络程序时,错误处理非常重要。我们需要了解Boost.Asio库提供的错误处理机制,以及如何正确处理和恢复可能发生的异常。 通过学习Boost.Asio的HTTP Server模块,我们可以提高我们的网络编程技能,了解HTTP协议的工作原理,以及如何使用C++编写高性能的HTTP服务器。这对于开发Web应用、服务端应用程序等领域都非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值