异步I/O操作
今天在看boost库的时候注意到异步I/O操作时,缓冲区有效性问题。
如何实现异步操作:以异步读操作为例async_read(buffer, handler);
void handler() {}
void function()
{
char buffer[1234];
async_read(buffer, handler);
}
当运行function时会不会有安全隐患,因为这时候缓冲区buffer已经被释放了!
需要了解异步操作做了哪些事情,async_read会将回调函数handler注册到能够检测到i/o事件的地方,并将buffer的地址也传递过去,用于存放接收到的数据。
因此需要保证缓冲区buffer的有效性。
一个例子:(从网上找来的,具体出处没找到)
- #include <iostream>
- #include <string>
- #include <boost/asio.hpp>
- #include <boost/bind.hpp>
- #include <boost/smart_ptr.hpp>
- using namespace boost::asio;
- using boost::system::error_code;
- using ip::tcp;
- struct CHelloWorld_Service{
- CHelloWorld_Service(io_service &iosev)
- :m_iosev(iosev),m_acceptor(iosev, tcp::endpoint(tcp::v4(), 1000))
- {
- }
- void start()
- {
- // 开始等待连接(非阻塞)
- boost::shared_ptr<tcp::socket> psocket(new tcp::socket(m_iosev));
- // 触发的事件只有error_code参数,所以用boost::bind把socket绑定进去
- m_acceptor.async_accept(*psocket,
- boost::bind(&CHelloWorld_Service::accept_handler, this , psocket, _1)
- );
- }
- // 有客户端连接时accept_handler触发
- void accept_handler(boost::shared_ptr<tcp::socket> psocket, error_code ec)
- {
- if (ec) return ;
- // 继续等待连接
- start();
- // 显示远程IP
- std::cout << psocket->remote_endpoint().address() << std::endl;
- // 发送信息(非阻塞)
- boost::shared_ptr<std::string> pstr(new std::string( "hello async world!" ));
- psocket->async_write_some(buffer(*pstr),
- boost::bind(&CHelloWorld_Service::write_handler, this , pstr, _1, _2)
- );
- }
- // 异步写操作完成后write_handler触发
- void write_handler(boost::shared_ptr<std::string> pstr,
- error_code ec, size_t bytes_transferred)
- {
- if (ec)
- std::cout<< "发送失败!" << std::endl;
- else
- std::cout<< *pstr << " 已发送" << std::endl;
- }
- private :
- io_service &m_iosev;
- ip::tcp::acceptor m_acceptor;
- };
- int main( int argc, char * argv[])
- {
- io_service iosev;
- CHelloWorld_Service sev(iosev);
- // 开始等待连接
- sev.start();
- iosev.run();
- return 0;
- }
在这个例子中,首先调用sev.start() 开 始接受客户端连接。由于async_accept 调 用后立即返回,start() 方 法 也就马上完成了。sev.start()在 瞬间返回后iosev.run() 开 始执行,iosev.run()方法是一个循环,负责分发异步回调事件,只 有所有异步操作全部完成才会返回。
这里有个问题,就是要保证start()方法中m_acceptor.async_accept 操 作所用的tcp::socket 对 象 在整个异步操作期间保持有效 (不 然系统底层异步操作了一半突然发现tcp::socket没了,不是拿人家开涮嘛-_-!!!),而且客户端连接进来后这个tcp::socket对象还 有用呢。这里的解决办法是使用一个带计数的智能指针boost::shared_ptr<tcp:: socket> ,并把这个指针作为参数绑定到回调函数上。
一旦有客户连接,我们在start()里给的回调函数accept_handler 就会被 调用,首先调用start()继续异步等待其 它客户端的连接,然后使用绑定进来的tcp::socket对象与当前客户端通信。
发送数据也使用了异步方式(async_write_some ), 同样要保证在整个异步发送期间缓冲区的有效性,所以也用boost::bind绑定了boost::shared_ptr<std:: string>。
异步I/O操作的更多相关文章
- 【原创-算法-实现】异步HTTP请求操作
一.说明 1) 这个类 是我 在真实项目中,优化解决真实问题 时,不参考第三方代码,完全由自己查阅MSDN官方文档 , 完成的一个真实生产环境中使用的功能类 2) 读者在使用此类时,请尊重原创,在代码 ...
- Task:取消异步计算限制操作 & 捕获任务中的异常
Why:ThreadPool没有内建机制标记当前线程在什么时候完成,也没有机制在操作完成时获得返回值,因而推出了Task,更精确的管理异步线程. How:通过构造方法的参数TaskCreationOp ...
- IOS异步和多线程操作&&在sqlite3中的应用
1,数据库I/O操作(异步) 数据库本身是存储在磁盘上.访问和修改数据库,即对磁盘进行读写,即I/O操作. 磁盘属于计算机硬件,具有DMA能力,不需要CPU干预,可以实现异步操作. I/O操作一般是消 ...
- asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案
之前碰到asp.net core异步进行新增操作并且需要判断某些字段是否重复的问题,进行插入操作的话会导致数据库中插入重复的字段!下面把我的解决方法记录一下,如果对您有所帮助,欢迎拍砖! 场景:EFC ...
- C# Windows异步I/O操作
1.简介 关于Windows的异步I/O操作,只要解决的是同步I/O操作的线程利用率问题,通过异步I/O Api来提升线程的利用率,提升系统的吞吐能力,将各种I/O操作交给线程池然后交由硬件设备执行, ...
- C#实现多级子目录Zip压缩解压实例 NET4.6下的UTC时间转换 [译]ASP.NET Core Web API 中使用Oracle数据库和Dapper看这篇就够了 asp.Net Core免费开源分布式异常日志收集框架Exceptionless安装配置以及简单使用图文教程 asp.net core异步进行新增操作并且需要判断某些字段是否重复的三种解决方案 .NET Core开发日志
C#实现多级子目录Zip压缩解压实例 参考 https://blog.csdn.net/lki_suidongdong/article/details/20942977 重点: 实现多级子目录的压缩, ...
- RabbitMQ实战场景(一):异步记录用户操作日志
传统的项目开发中业务流程以串行方式,执行了模块1—>模块2–>模块3 而我们知道,这个执行流程其实对于整个程序来讲是有一定的弊端的,主要有几点: (1)整个流程的执行响应等待时间比较长; ...
- mvc file控件无刷新异步上传操作
前言 上传文件应该是很常见必不可少的一个操作,网上也有很多提供的上传控件.今天遇到一个问题:input控件file无法进行异步无刷新上传.真真的感到别扭.所以就尝试这去处理了一下.主要分三个部分:上传 ...
- 进程理论 阻塞非阻塞 同步异步 I/O操作
1.什么是进程 进程指的是一个正在运行的程序,进程是用来描述程序执行过程的虚拟概念 进程的概念起源于操作系统,进程是操作系统最核心的概念,操作系统其它所有的概念都是围绕进程来的 2.操作系统 操作系统 ...
随机推荐
- Web 开发人员系统重装备忘录
准备工作: 一.配置IIS 软件安装: 一.大块头: 1.VS2005 1.VS2005SP1 2.VSS 2005 2.VS2008 1.VS2008TeamExplorer 2.VS2008SP1 ...
- List集合的remove一个对象的方法
import java.util.ArrayList;import java.util.List;class A{ public boolean equals(Object obj){ return ...
- js数组中去除重复对象及去除空对象的方法
(function(){//去除数组中重复对象 var unique = {}; arr.forEach(function(a){ unique[ JSON.stringify(a) ] = 1 }) ...
- python反射原理
1.反射原理 通过字符串的形式导入模块: __import__(),可以以字符串的形式导入模块. 通过字符串的形式导入函数: 反射: 根据字符串去某个对象里面取东西,可以是字符串,函数,数字. 根据字 ...
- vs2012中将图片放到resource中进行调用
1.在项目中新建一个名叫resource的文件夹,然后将所需图片信息放入该文件夹,如图 2.右击该项目,选择属性->资源选项卡,步骤如图所示 点击添加现有文件,然后找到你刚刚添加的resourc ...
- document.createElement()方法
document.createElement()是在对象中创建一个对象,主要和appendChild() 方法或者insertBefore() 方法联合使用. appendChild() 方法在节点的 ...
- 一步一步了解Cocos2dx 3.0 正式版本开发环境搭建(Win32/Android)
cocos2d-x 3.0发布有一段时间了,作为一个初学者,我一直觉得cocos2d-x很坑.每个比较大的版本变动,都会有不一样的项目创建方式,每次的跨度都挺大…… 但是凭心而论,3.0RC版本开始 ...
- 修改maven默认的JDK编译版本
1.全局模式(settings.xml) <profiles> <profile> <id>jdk-1.8</id> <activation> ...
- 使用SeasLog打造PHP项目中的高性能日志组件(一)
云智慧(北京)科技有限公司 高驰涛 什么是SeasLog SeasLog是一个C语言编写的PHP扩展,提供一组规范标准的功能函数,在PHP项目中方便.规范.高效地写日志,以及快速地读取和查询日志. 为 ...
- ROC曲线、AUC、Precision、Recall、F-measure理解及Python实现
本文首先从整体上介绍ROC曲线.AUC.Precision.Recall以及F-measure,然后介绍上述这些评价指标的有趣特性,最后给出ROC曲线的一个Python实现示例. 一.ROC曲线.AU ...