• boost::asio基本使用


    一、Asio网络库

      截止到C++17,C++标准库都没有加入网络通信库。实际项目网络编程是非常常见的功能,直接使用操作系统API是低效率且不稳定的,比较好的方法是借助第三方成熟可靠的网络库。据我所知C++中目前比较有名的网络库有ACE、libevent和boost.Asio,这三个库都是跨平台的,各有特色,对于一般的应用来说,使用这些库都是没什么问题。由于C++标准库和boost库的亲缘关系,我经常使用boost中其它的库,所以选择了Asio库。在网络上搜索了大家对Asio的评价,发现Asio库作为跨平台的网络库还是相当优秀的。

      Linux系统高效网络I/O是epoll,windows系统高效的网络I/O是iocp,epoll是一种同步I/O复用技术,iocp是异步I/O。同步I/O指内核通知应用程序数据有了,应用程序可以获取了;异步I/O是内核负责读数据,读好后通知应用程序可以用了。所以一般来说异步I/O相比同步I/O的效率更高一些,但是Linux中异步I/O(aio)并不比epoll高效。为了使的Asio库跨平台,最终Asio选择Linux系统在epoll的基础上用iocp的思想的封装一层,这在一定上损失了Linux平台I/O的效率。总的来说Asio网络通信库是主动器模式(proactor),而libevent使用的是reactor模式。

    二、反应器模式/主动器模式

      反应器是比较容易理解的I/O模式,也是使用比较多的模式。主要内容来自于《IO设计模式:Reactor和Proactor对比》。

     

    Reactor包含如下角色:

    • Handle 句柄;用来标识socket连接或是打开文件;
    • Synchronous Event Demultiplexer:同步事件多路分解器:由操作系统内核实现的一个函数;用于阻塞等待发生在句柄集合上的一个或多个事件;(如select/epoll;)
    • Event Handler:事件处理接口
    • Concrete Event HandlerA:实现应用程序所提供的特定事件处理逻辑;
    • Reactor:反应器,定义一个接口,实现以下功能: 
      1)供应用程序注册和删除关注的事件句柄; 
      2)运行事件循环; 
      3)有就绪事件到来时,分发事件到之前注册的回调函数上处理;

     Proactor主动器模式包含如下角色

    • Handle 句柄;用来标识socket连接或是打开文件;
    • Asynchronous Operation Processor:异步操作处理器;负责执行异步操作,一般由操作系统内核实现;
    • Asynchronous Operation:异步操作
    • Completion Event Queue:完成事件队列;异步操作完成的结果放到队列中等待后续使用
    • Proactor:主动器;为应用程序进程提供事件循环;从完成事件队列中取出异步操作的结果,分发调用相应的后续处理逻辑;
    • Completion Handler:完成事件接口;一般是由回调函数组成的接口;
    • Concrete Completion Handler:完成事件处理逻辑;实现接口定义特定的应用处理逻辑;

      主动和被动以主动写为例,Reactor将handle放到select(),等待可写就绪,然后调用write()写入数据;写完处理后续逻辑;Proactor调用aoi_write后立刻返回,由内核负责写操作,写完后调用相应的回调函数处理后续逻辑;可以看出,Reactor被动的等待指示事件的到来并做出反应;它有一个等待的过程,做什么都要先放入到监听事件集合中等待handler可用时再进行操作;Proactor直接调用异步读写操作,调用完后立刻返回。

     三、基本使用

     1.基本的同步客户端架构

    1 using boost::asio;
    2 io_service service;
    3 ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 2001);
    4 ip::tcp::socket sock(service);
    5 sock.connect(ep);

    2.基本的同步服务器架构

     1 typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
     2 io_service service;
     3 ip::tcp::endpoint ep( ip::tcp::v4(), 2001)); // listen on 2001
     4 ip::tcp::acceptor acc(service, ep);
     5 while ( true) {
     6     socket_ptr sock(new ip::tcp::socket(service));
     7     acc.accept(*sock);
     8     boost::thread( boost::bind(client_session, sock));
     9 }
    10 void client_session(socket_ptr sock) {
    11     while ( true) {
    12         char data[512];
    13         size_t len = sock->read_some(buffer(data));
    14         if ( len > 0)
    15             write(*sock, buffer("ok", 2));
    16     }

    3.基本的异步客户端架构

    1 using boost::asio;
    2 io_service service;
    3 ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), 2001);
    4 ip::tcp::socket sock(service);
    5 sock.async_connect(ep, connect_handler);
    6 service.run();
    7 void connect_handler(const boost::system::error_code & ec) {
    8     // 如果ec返回成功我们就可以知道连接成功了
    9 }

    4.基本的异步服务器架构

     1 using boost::asio;
     2 typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
     3 io_service service;
     4 ip::tcp::endpoint ep( ip::tcp::v4(), 2001)); // 监听端口2001
     5 ip::tcp::acceptor acc(service, ep);
     6 socket_ptr sock(new ip::tcp::socket(service));
     7 start_accept(sock);
     8 service.run();
     9 void start_accept(socket_ptr sock) {
    10     acc.async_accept(*sock, boost::bind( handle_accept, sock, _1) );
    11 }
    12 void handle_accept(socket_ptr sock, const boost::system::error_code &
    13 err) {
    14     if ( err) return;
    15     // 从这里开始, 你可以从socket读取或者写入
    16     socket_ptr sock(new ip::tcp::socket(service));
    17     start_accept(sock);
    18 }

    参考:IO设计模式:Reactor和Proactor对比

            《Boost.Asio C++网络编程》

  • 相关阅读:
    Failed to load resource: the server responded with a status of 413 (Request Entity Too Large)
    钱能解决的都是小事——北漂18年(78)
    mysql 排序
    innodb和myisam表排序
    perl 内部字节字符转换
    encode_json 转换给定的perl数据结构为一个UTF-8编码的 2进制字符串 decode_json把UTF-8字节转换成字符
    perl /g
    perl 循环截取字符串
    eclipse报错:Compilation unit name must end with .java, or one of the registered Java-like exten
    用 Flask 来写个轻博客 (30) — 使用 Flask-Admin 增强文章管理功能
  • 原文地址:https://www.cnblogs.com/wxquare/p/6953267.html
Copyright © 2020-2023  润新知