热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C++BoostAsio:I/O服务、I/O对象与网络编程详解

使用Boost.Asio进行异步数据处理的应用程序主要依赖于两个核心概念:I/O服务和I/O对象。I/O服务抽象了操作系统接口,使得异步操作能够高效地执行。I/O对象则代表了具体的网络资源,如套接字和文件描述符,通过这些对象可以实现数据的读写操作。本文详细介绍了这两个概念在Boost.Asio中的应用及其在网络编程中的重要性。

I/O 服务与I/O 对象

使用Boost的Asio进行异步处理数据的应用程序基于两个概念:


  • I/O服务
  • I/O对象

I/O服务抽象了操作系统的接口,允许第一时间进行异步数据处理,而I/O对象则初始化特定的操作。


// I/O服务
boost::asio:io_service// 用于网络发送和接收数据
boost::asio::ip::tcp::socket// 计时器
boost::asio::deadline_timer

#include
#includevoid handler1(const boost::system::error_code &ec)
{std::cout <<"5 s." <}void handler2(const boost::system::error_code &ec)
{std::cout <<"10 s." <}int main()
{//1 初始化 I/O服务boost::asio::io_service io_service;//2 初始化I/O对象timer,使用boost::posix_time进行时间处理boost::asio::deadline_timer timer1(io_service, boost::posix_time::seconds(5));//3 该函数调用会立即返回timer1.async_wait(handler1);boost::asio::deadline_timer timer2(io_service, boost::posix_time::seconds(10));timer2.async_wait(handler2);//4 启动异步处理&#xff0c;进入阻塞状态io_service.run();return 0;
}

可扩展性与多线程


用boost asio这样的库开发程序&#xff0c;与一般的C&#43;&#43;风格不同。哪些可能需要较长时间才返回的函数不再以顺序的方式来调用。不在是调用阻塞式的函数&#xff0c;boost asio是启动一个异步操作。而那些需要在操作结束后调用的函数则实现为相应的句柄。这种方法的缺点是&#xff0c;本来顺序执行的功能变得在物理上分割开来了&#xff0c;从而令相应的代码更难理解。
象 Boost asio 这样的库通常是为了令应用程序具有更高的效率。应用程序不在需要等待特定的函数执行完成&#xff0c;而可以在期间执行其它任务&#xff0c;如开始另一个需要较长时间的操作。


#include
#include
#includevoid handler1(const boost::system::error_code &ec)
{std::cout <<"5 s." <}void handler2(const boost::system::error_code &ec)
{std::cout <<"5 s." <}// 使用两个 I/O 服务
boost::asio::io_service io_service1;
boost::asio::io_service io_service2;void run1()
{io_service1.run();
}void run2()
{io_service2.run();
}int main()
{boost::asio::deadline_timer timer1(io_service1, boost::posix_time::seconds(5));timer1.async_wait(handler1);boost::asio::deadline_timer timer2(io_service2, boost::posix_time::seconds(5));timer2.async_wait(handler2);boost::thread thread1(run1);boost::thread thread2(run2);thread1.join();thread2.join();
}

这个应用程序的功能与前一个相同。在一定条件下使用多个I/O服务是有好处的&#xff0c;每个I/O服务有自己的线程&#xff0c;最好是运行在各自的处理器内核上&#xff0c;这样每一个异步操作连同它们的句柄就可以局部化执行。如果没有远端的数据或函数需要访问&#xff0c;那么每一个I/O服务就像一个小的自主应用。这里的局部和远端是指像高速缓存&#xff0c;内存页这样的资源。由于在确定优化策略之前需要对底层硬件&#xff0c;操作系统&#xff0c;编译器以及潜在的瓶颈有专门的了解&#xff0c;所以应该仅在清楚这些好处的情况下使用多个I/O服务。


网络编程

虽然 boost.asio 是一个可以异步处理任何种类数据的库&#xff0c;但是它主要被用于网络编程。这是由于&#xff0c;事实上Boost.Asio在加入其他I/O对象之前很久就已经支持网络功能了。网络功能是异步处理的一个很好的例子&#xff0c;因为通过网络进行数据传输可能会需要较长时间&#xff0c;从而不能直接获得确认或错误条件。

#include
#include
#include
#include boost::asio::io_service io_service;
// 域名解析器
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::socket sock(io_service);
boost::array buffer; void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred)
{ if (!ec) { std::cout <} void connect_handler(const boost::system::error_code &ec)
{ if (!ec) { boost::asio::write(sock, boost::asio::buffer("GET / HTTP 1.1\r\nHost: graycatya.com\r\n\r\n")); sock.async_read_some(boost::asio::buffer(buffer), read_handler); }
} void resolve_handler(const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator it)
{ if (!ec) { sock.async_connect(*it, connect_handler);}
} int main()
{ boost::asio::ip::tcp::resolver::query query("www.graycatya.com", "80"); resolver.async_resolve(query, resolve_handler); io_service.run();
}

  • boost::asio::ip::tcp::resolver

域名解析也是一个需要连接到互联网的过程。 有些专门的PC&#xff0c;被称为DNS服务器&#xff0c;其作用就象是电话本&#xff0c;它知晓哪个IP地址被赋给了哪台PC。 由于这个过程本身的透明的&#xff0c;只要明白其背后的概念以及为何需要。


  • async_resolve

一旦域名解析成功或被某个错误中断&#xff0c;resolve_handler() 函数就会被调用。

*** 软件执行流程 ***


  1. 应用创建一个类型(bost::asio::ip::tcp::resolver::query)对象query&#xff0c;表示一个查询&#xff0c;这个查询被传递给async_resolve()方法以解析该域名。
  2. 当域名解析完成后&#xff0c;resolve_handler()被调用 访问I/O对象sock,用由迭代器it所提供的解析后地址创建一个连接&#xff0c;如果解析成功&#xff0c;则存有错误条件的对象ec被设为0&#xff0c;只有在这种情况下&#xff0c;才会相应地访问socket以创建连接。服务器地地址是通过类型为boost::asio::ip::tcp::resolver::iterator提供。
  3. 调用了 async_connect()方法之后&#xff0c;connect_handler()会被自动调用。在该句柄地内部&#xff0c;会访问ec对象以检查连接是否已建立。如果连接是有效的&#xff0c;则对相应的socket调用async_read_some()方法&#xff0c;启动读数据操作。为保存接收到的数据&#xff0c;要提供一个缓冲区作为第一个参数。在以下例子中&#xff0c;缓冲区类型是boost::array。
  4. 每当有一个或多个字节被接收并保存至缓冲区时&#xff0c;read_handler()函数就会被调用。准确的字节数通过std::size_t 类型的参数 bytes_transferred 给出。同样的规则&#xff0c;该句柄应该首先看看参数ec以检查有没有接收错误。如果是成功接收&#xff0c;则将数据写出至标准输出流。
    注意&#xff1a;read_handler() 在将数据写出至std::cout之后&#xff0c;会再次调用async_read_some()方法。这是必需的&#xff0c;因为无法保证仅在一次异步操作中就可以接收到整个网页。async_read_some() 和 read_handler() 的交替调用只有当连接被破坏时才中止&#xff0c;如当web服务器已经传送完整个网页时。这种情况下&#xff0c;在read_handler() 内部将报告一个错误&#xff0c;以防止进一步将数据输出至标准输出流&#xff0c;以及进一步对该socket调用async_read() 方法。

推荐阅读
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文详细探讨了VxWorks操作系统中双向链表和环形缓冲区的实现原理及使用方法,通过具体示例代码加深理解。 ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • 文件描述符、文件句柄与打开文件之间的关联解析
    本文详细探讨了文件描述符、文件句柄和打开文件之间的关系,通过具体示例解释了它们在操作系统中的作用及其相互影响。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • Codeforces Round #566 (Div. 2) A~F个人题解
    Dashboard-CodeforcesRound#566(Div.2)-CodeforcesA.FillingShapes题意:给你一个的表格,你 ... [详细]
  • 本文探讨了如何通过最小生成树(MST)来计算严格次小生成树。在处理过程中,需特别注意所有边权重相等的情况,以避免错误。我们首先构建最小生成树,然后枚举每条非树边,检查其是否能形成更优的次小生成树。 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文详细介绍了C语言中链表的两种动态创建方法——头插法和尾插法,包括具体的实现代码和运行示例。通过这些内容,读者可以更好地理解和掌握链表的基本操作。 ... [详细]
author-avatar
陌城花开2010
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有