Boost.Asio使用实例
来源:互联网 发布:reshade画面优化补丁 编辑:程序博客网 时间:2024/05/27 20:59
2、简略的过程分析。以socket的连接操作为例:
你的程序中需要至少定义一个io_service对象:boost::asio::io_service io_service。io_service表示程序到操作系统I/O服务的“连接”。
为执行I/O操作,还需要一个I/O对象(通常需要使用io_service构造),如一个TCP套接字:boost::asio::ip::tcp::socket socket(io_service)。
1)同步的连接过程中,发生以下事件序列(对应下面的左图):
(1)程序通过I/O对象启动连接操作: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对象抛出boost::system::system_error异常。
如果是使用以下方式,则只设置错误码,不会抛出异常:
boost::system::error_code ec;socket.connect(server_endpoint, ec);
2)异步的连接过程中,发生以下事件序列(对应下面的中图和右图):
(1)程序通过I/O对象启动连接操作:socket.async_connect(server_endpoint, your_completion_handler);
your_completion_handler是一个函数(对象),原型:void your_completion_handler(const boost::system::error_code& ec);
(2)I/O对象将请求转发给io_service;
(3)io_service发信号给操作系统,告知它去开始一个异步的连接操作;
一段时间过去... ...注意,在同步的情形下,程序会一直等待连接操作完成,而异步则是先立即返回。
(4)连接操作完成时,操作系统把结果放在队列中;
(5)程序必须调用io_service::run()(或类似函数)以取得操作结果。一般在你刚启动第一个异步操作时就要调用run();
io_service对象未停止(stopped()返回false)且还有未完成的操作时,run()会一直阻塞,否则直接返回。
我的理解(io_service对象未停止时):如果当前有未完成的异步操作且队列为空,则需要等待,因此run()将阻塞(在Linux下借助pstack可知是阻塞于epoll_wait()或pthread_cond_wait()等)。操作系统完成某个异步操作后,把结果放到队列并通知应用程序。run()被“唤醒”,从队列中取出结果并调用相应的回调函数;如果当前没有未完成的异步操作且队列为空,表示所有异步操作已经完成,则run()将直接返回;当然,如果当前队列非空,则run()直接取出结果并调用回调函数。
asio保证了回调函数只会被run()所在线程调用。因此,若没有run(),回调函数永远不会被调用。
(6)在run()中io_service将操作结果取出队列并翻译成error_code,然后传递给your_completion_handler。
3、例子:
// 一个简单的回显服务器#include <iostream>#include <memory>#include <array>#include <boost/asio.hpp>using boost::asio::ip::tcp;// 服务器和某个客户端之间的“会话”// 负责处理读写事件class session : public std::enable_shared_from_this<session>{public: session(tcp::socket s) : socket_(std::move(s)) {} void start() { async_read(); }private: void async_read() { auto self(shared_from_this()); socket_.async_read_some(boost::asio::buffer(data_), // 异步读 [this, self](const boost::system::error_code &ec, size_t bytes_transferred) // 读操作完成时回调该函数 { // 捕获`self`使shared_ptr<session>的引用计数增加1,在该例中避免了async_read()退出时其引用计数变为0 if (!ec) async_write(bytes_transferred); // 读完即写 } ); } void async_write(std::size_t length) { auto self(shared_from_this()); boost::asio::async_write(socket_, boost::asio::buffer(data_, length), // 异步写 [this, self](const boost::system::error_code &ec, size_t) { if (!ec) async_read(); } ); } tcp::socket socket_; // “会话”基于已经建立的socket连接 std::array<char, 1024> data_;};// 服务器类// 监听客户端连接请求(async_accept)。与某个客户端建立socket连接后,为它创建一个sessionclass server{public: server(boost::asio::io_service &io_service, short port) : acceptor_(io_service, tcp::endpoint(tcp::v4(), port)), socket_(io_service) { async_accept(); }private: void async_accept() { acceptor_.async_accept(socket_, std::bind(&server::handle_accept, this, std::placeholders::_1)); // 异步accept。socket连接建立后,调用handle_accept() } void handle_accept(const boost::system::error_code &ec) { if (!ec) { std::shared_ptr<session> session_ptr(new session(std::move(socket_))); session_ptr->start(); } async_accept(); // 继续监听客户端连接请求 } tcp::acceptor acceptor_; tcp::socket socket_;};int main(int argc, char* argv[]){ boost::asio::io_service io_service; server s(io_service, 52014); io_service.run(); return 0;}
参考资料:
http://www.boost.org/
- boost::asio 使用实例
- Boost.Asio使用实例
- boost之asio同步io使用实例
- boost之asio异步io使用实例
- boost之asio实现定时器使用实例
- boost.asio 使用点滴
- Boost Asio服务器使用
- boost asio使用注意事项
- boost::asio server编程实例
- Boost.Asio的使用技巧
- Boost.Asio的使用技巧
- Boost.Asio的使用技巧
- Boost.Asio的使用技巧
- Boost.Asio的使用技巧
- Boost.Asio的使用技巧
- Boost-Asio的使用技巧
- boost::asio::steady_timer基础使用
- Boost.Asio的使用技巧
- OSI七层与TCP/IP五层网络架构详解
- Android中TextView:maxWidth、maxLength、maxEms的区别
- Spring MVC 接收POST表单请求,获取参数总结
- 【Mybatis】使用java方式实现SM框架整合
- 如何迁移整个git仓库
- Boost.Asio使用实例
- windows 常用命令和设置
- MFC、WTL、WPF、wxWidgets、Qt、GTK、Cocoa、VCL 各有什么特点?
- 如何让 Qt 的程序使用 Sleep
- Boost.Asio技术文档汇总
- 关于Android中常用的四种线程池的介绍
- 路漫漫兮,吾将上下而求索
- ChannelAwareMessageListener 与MessageListener
- windows下用cmd切换目录