Boost.ASIO简要分析-1 初窥

Boost.Asio是一个主要用于网络及底层I/O编程的跨平台C++库。

1. 初窥

Boost.Asio支持对I/O对象进行同步及异步操作。

1.1 同步操作

同步操作的事件顺序如下图所示:

1) 调用者调用I/O对象的connect函数开始连接操作,socket.connect(server_endpoint);

2) I/O对象将连接请求传递给io_service;

3) io_service调用操作系统函数;

4) 操作系统返回结果给io_service;

5) io_service将结果以boost::system::error_code类型传递给I/O对象;

6) I/O对象将结果告诉调用者。

需要注意的是如果用户在第1步中使用socket.connect(server_endpoint)这个函数开始连接操作,那么如果连接过程中出现错误,I/O对象将以抛异常的行为来告诉你出错了(因为它想告诉你出错了,又没有可接收错误的参数),所以没养成写try/catch习惯的朋友需要注意了^_^。当然,我们可以使用socket.connect(server_endpoint, ec) 这个函数就可以避免未捕获异常而导致的程序崩溃问题。变量ec是boost::system::error_code类型,用于接收错误信息。

从上述流程我们可以看出,步骤1->2->3->4->5->6是个逐层调用及返回的过程,也就是说调用者发出连接请求(1)后就必须等待至所有操作完成后才返回(6),表明这是个同步操作。

1.2 异步操作

异步操作的事件顺序如下图所示:

1) 和同步操作一样,调用者也是调用I/O对象开始连接操作,只不过函数变成async开头,socket.async_connect(server_endpoint, your_completion_handler);

注意此处your_completion_handler这个参数,这个handler用于稍后讲到的回调操作。

2) 和同步操作一样,I/O对象将请求传递给io_service。

3) 和同步操作一样,io_service调用操作系统函数以执行连接操作。只是此时,io_service告诉系统它要发起一个异步连接请求。

和同步调用的区别在于,完成3这一步骤之后,当前线程就返回到调用者处。

过了一段时间后。。。

4) 操作系统完成连接操作,并把结果放到一个完成队列中。

5) 用户程序必须调用io_service::run()或类似函数,才能从4)中所述的队列中取出结果。

6) 在io_service::run()内部,将结果取出并转化为error_code,并调用传递给1)中所述的回调函数。

1.3 同步VS异步

1) 同步代码,编写简单,不需要回调函数,且不用考虑烦人的Buffer问题;

2) 异步代码,线程不会阻塞住,可以去做别的事情,充分利用CPU资源;

3) 对于客户端而言,操作一般都是顺序的,所以客户端一般采取同步操作。

4) 对于服务端而言,如果采用同步操作的话,就没有把CPU资源完全利用起来,当然,也可以采用多线程的方式去充分利用CPU资源。比如,对每个请求都建立一条线程与之通信,这样的后果就是会导致线程数量过大(Mongo里面就是这样的,当然连接数有上限),线程数量过大的后果是线程切换的时间浪费。如果采用异步方式的话,服务端只需将异步请求告诉操作系统去执行,自己就可以去忙别的了,当然也只需建立一个或多个工作线程读取完成队列即可。

时间: 2024-10-27 08:50:35

Boost.ASIO简要分析-1 初窥的相关文章

Boost.ASIO简要分析-4 多线程

4. 多线程 一般情况下,服务端开启一条线程做io_service::run()工作就足够了.但是,有些情况下可能会变得很糟糕. 从之前的分析,我们知道异步操作的一个关键步骤就是io_service回调我们注册的handler.现在假设客户端与服务端建立了四个socket连接,相应的I/O对象分别为socket1, socket2, socket3, socket4,并且假设io_service现在正在处理socket1注册的handler.如果这个handler处理的过程很长,那么在这期间so

Boost.ASIO简要分析-5 多io_service

5. 多io_service 前面那篇讲到了多线程的用法.这篇讲一下多io_service的用法,大家可参考下官方提供的HTTP Server 2(an io_service-per-CPU)这个例子. 官方提供的例子中,使用方法很简单,建立一个io_service_pool,然后对每一个io_service开一个线程去让它跑起来(毕竟,io_service::run这个函数在有任务的时候会一直工作的,只有开多个线程才做到不影响别的io_service).当然,我们也可以为每个io_servic

Boost::asio io_service 实现分析

io_service的作用 io_servie 实现了一个任务队列,这里的任务就是void(void)的函数.Io_servie最常用的两个接口是post和run,post向任务队列中投递任务,run是执行队列中的任务,直到全部执行完毕,并且run可以被N个线程调用.Io_service是完全线程安全的队列. Io_servie的接口 提供的接口有run.run_one.poll.poll_one.stop.reset.dispatch.post,最常用的是run.post.stop Io_se

boost.asio源码剖析(三) ---- 流程分析

* 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: 1 #include <iostream> 2 #include <boost/asio.hpp> 3 4 // 异步连接回调函数 5 void on_connect(boost::system::error_code ec) 6 { 7 if (ec) // 连接失败, 输出错误码 8 std::cout << "async connect error:"

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

最近在做服务器的稳定性的相关测试,服务器的网络底层使用的是boost asio,然后自己做的二次封装以更好的满足需求. 服务器昨天晚上发现crash了一次,之前测试了将近半个多月,有一次是莫名的退出了,不过由于是新的测试服,忘记将ulimit -c进行修改了,所以没有coredump,这次又发生了. coredump如下: #0 0x0000000000000091 in ?? () #1 0x0000000000459729 in ClientHandler::HandleConnect(cp

boost::asio的io_service处理过程

1.主线程定义回调对象 2.调用io object的操作 3.io object会另开线程,定义opertion op来执行操作,同时将回调对象加到op的do_complete上.进行操作 4.完成操作加入完成队列 5.io_service线程循环从完成队列取事件,调用其事件对应的回调函数 Operation 还记得前面我们在分析resolver的实现的时候,挖了一个关于operation的坑?为了不让自己陷进去,现在来填吧:接下来我们就来看看asio中的各种operation. 和前面提到过的

Hadoop学习笔记(9) ——源码初窥

Hadoop学习笔记(9) ——源码初窥 之前我们把Hadoop算是入了门,下载的源码,写了HelloWorld,简要分析了其编程要点,然后也编了个较复杂的示例.接下来其实就有两条路可走了,一条是继续深入研究其编程及部署等,让其功能使用的淋漓尽致.二是停下来,先看看其源码,研究下如何实现的.在这里我就选择第二条路. 研究源码,那我们就来先看一下整个目录里有点啥: 这个是刚下完代码后,目录列表中的内容. 目录/文件 说明 bin 下面存放着可执行的sh命名,所有操作都在这里 conf 配置文件所在

C/C++利用Boost::Asio网络库建立自己的Socket服务器

引言 寸光阴,当下我们或许更需要利用现有的知识,应用现有的技术.网络是当前互联网的根本,了解网络便开始显得极其重要.今天我们利用Boost库中Asio部分,浅尝网络服务器.此处不做过于深入的开展,为达成学习目的,只做简单的异步并发服务器. 注意:本篇代码没有直接引用boost等命名空间,为的是新入门Boost的同学能够更好的了解每个参数在boost的具体命名空间位置,有助于更好的理解boost的布局. 版权所有:_OE_,转载请注明出处:http://blog.csdn.net/csnd_ayo

jQuery源码学习(2):选择器初窥

选择器初窥 代码架构: jQuery选择器可以依照传入数据的类型分为五大类: 传入字符串:$("div"), $("#id"), $(".div1"),$(".div p.title") 传入html代码:$("<div></div>"), $("<div>1</div><div>2</div>") 传入对象:$(d