一、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.基本的同步客户端架构

 using boost::asio;
io_service service;
ip::tcp::endpoint ep( ip::address::from_string("127.0.0.1"), );
ip::tcp::socket sock(service);
sock.connect(ep);

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

 typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
io_service service;
ip::tcp::endpoint ep( ip::tcp::v4(), )); // listen on 2001
ip::tcp::acceptor acc(service, ep);
while ( true) {
socket_ptr sock(new ip::tcp::socket(service));
acc.accept(*sock);
boost::thread( boost::bind(client_session, sock));
}
void client_session(socket_ptr sock) {
while ( true) {
char data[];
size_t len = sock->read_some(buffer(data));
if ( len > )
write(*sock, buffer("ok", ));
}

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

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

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

 using boost::asio;
typedef boost::shared_ptr<ip::tcp::socket> socket_ptr;
io_service service;
ip::tcp::endpoint ep( ip::tcp::v4(), )); // 监听端口2001
ip::tcp::acceptor acc(service, ep);
socket_ptr sock(new ip::tcp::socket(service));
start_accept(sock);
service.run();
void start_accept(socket_ptr sock) {
acc.async_accept(*sock, boost::bind( handle_accept, sock, _1) );
}
void handle_accept(socket_ptr sock, const boost::system::error_code &
err) {
if ( err) return;
// 从这里开始, 你可以从socket读取或者写入
socket_ptr sock(new ip::tcp::socket(service));
start_accept(sock);
}

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

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

boost::asio基本使用的更多相关文章

  1. c++ boost asio库初学习

    前些日子研究了一个c++的一个socket库,留下范例代码给以后自己参考. 同步server: // asio_server.cpp : コンソール アプリケーションのエントリ ポイントを定義します. ...

  2. 如何在多线程leader-follower模式下正确的使用boost::asio。

    #include <assert.h> #include <signal.h> #include <unistd.h> #include <iostream& ...

  3. BOOST.Asio——Tutorial

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

  4. BOOST.Asio——Overview

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

  5. boost asio sync

    Service: #include<boost/asio.hpp> #include<boost/thread.hpp> #include<iostream> #i ...

  6. 网络库crash以及boost asio strand dispath分析

    最近在做服务器的稳定性的相关测试,服务器的网络底层使用的是boost asio,然后自己做的二次封装以更好的满足需求. 服务器昨天晚上发现crash了一次,之前测试了将近半个多月,有一次是莫名的退出了 ...

  7. boost asio tcp server 拆分

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

  8. boost::asio 使用实例

    #include <iostream> #include <boost/asio.hpp> using namespace std; using namespace boost ...

  9. boost.asio源码剖析(四) ---- asio中的泛型概念(concepts)

    * Protocol(通信协议) Protocol,是asio在网络编程方面最重要的一个concept.在第一章中的levelX类图中可以看到,所有提供网络相关功能的服务和I/O对象都需要Protoc ...

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

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

随机推荐

  1. FreeBSD查看即时网络流量

    1.数据包 “netstat 1″一秒钟累计一次,”netstat 2″两秒钟累计一次.依此类推 2.查看网卡流量:”systat -if 1″每秒钟刷新一次,”systat -if 2″两秒钟刷新一 ...

  2. C++互斥器:Semaphores

    类似于Mutex,但信号量Semaphores不仅仅是锁和解锁那么简单,更高级的是,可以被锁住最多n次. 其中这个n是信号量被产生时指定的n.该值常常被用来代表“可以锁定住一份资源”的线程个数. 可以 ...

  3. IE下 input 的父级标签被 disabled 之后引发的怪异行为

    前段时间做了个网盘类的项目,意外发现了这个情况 IE下,将input的父级标签增加 disabled 属性之后,input 的行为变得怪异: 1.input 背景变灰,疑似也被disabled 了. ...

  4. kubernetes 应用基本准则

    不要直接部署裸的Pod. 为工作负载选择合适的Controller. 使用Init容器确保应用程序被正确的初始化. 在应用程序工作负载启动之前先启动service. 使用Deployment hist ...

  5. spring mvc配置ObjectMapper忽略无法识别的字段,以及一些博客推荐

    通过Spring的MethodInvokingFactoryBean类实现的调用configure方法,此方法返回调用该方法的本身实例. 配置完毕后,可以在spring mvc的消息处理器中使用,为了 ...

  6. 在c#客户端程序中使用log4net

    为什么使用log4net 有些日志语句只是在开发中用于调试的,不应该在Release版本中输出,log4net通过配置文件可以为Debug和Release不同的模式设置不同的输出级别来控制,而且如果已 ...

  7. 爬虫浅谈一:一个简单c#爬虫程序

    这篇文章只是简单展示一个基于HTTP请求如何抓取数据的文章,如觉得简单的朋友,后续我们再慢慢深入研究探讨. 图1: 如图1,我们工作过程中,无论平台网站还是企业官网,总少不了新闻展示.如某天产品经理跟 ...

  8. 记录一下获取浏览器可视区域的大小的js

    function GetPageSize() { var xScroll, yScroll; if (window.innerHeight && window.scrollMaxY) ...

  9. 关于gridview改变行内容事件需要点击别的行或控件才能执行

    一般的datagridview控件: this.dgvAssetList.CurrentCell = null;//取消datagridview行的编辑状态 Dev gridcontrol控件  Gr ...

  10. js图片自适应尺寸居中函数处理

    /* | autoSerializePicture.js 自适应格式化图片 | auther : baichaohua/2017-09-21 +---------------------------- ...