热门标签 | 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() 方法。

推荐阅读
  • 深入解析零拷贝技术(Zerocopy)及其应用优势
    零拷贝技术(Zero-copy)是Netty框架中的一个关键特性,其核心在于减少数据在操作系统内核与用户空间之间的传输次数。通过避免不必要的内存复制操作,零拷贝显著提高了数据传输的效率和性能。本文将深入探讨零拷贝的工作原理及其在实际应用中的优势,包括降低CPU负载、减少内存带宽消耗以及提高系统吞吐量等方面。 ... [详细]
  • 本文将介绍一种扩展的ASP.NET MVC三层架构框架,并通过使用StructureMap实现依赖注入,以降低代码间的耦合度。该方法不仅能够提高代码的可维护性和可测试性,还能增强系统的灵活性和扩展性。通过具体实践案例,详细阐述了如何在实际开发中有效应用这一技术。 ... [详细]
  • 本文提供了 RabbitMQ 3.7 的快速上手指南,详细介绍了环境搭建、生产者和消费者的配置与使用。通过官方教程的指引,读者可以轻松完成初步测试和实践,快速掌握 RabbitMQ 的核心功能和基本操作。 ... [详细]
  • 深入解析Wget CVE-2016-4971漏洞的利用方法与安全防范措施
    ### 摘要Wget 是一个广泛使用的命令行工具,用于从 Web 服务器下载文件。CVE-2016-4971 漏洞涉及 Wget 在处理特定 HTTP 响应头时的缺陷,可能导致远程代码执行。本文详细分析了该漏洞的成因、利用方法以及相应的安全防范措施,包括更新 Wget 版本、配置防火墙规则和使用安全的 HTTP 头。通过这些措施,可以有效防止潜在的安全威胁。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • JVM参数设置与命令行工具详解
    JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。 ... [详细]
  • 内网传送门【题目分析】在本次NOIP模拟赛中,题目主要考察了排列树与组合数学的综合应用,特别是拓扑排序的计算方法。题目的核心在于如何高效地求解树结构中的所有可能拓扑排序方案数,这对参赛者的算法设计和数学基础提出了较高要求。通过深入解析每个节点的排列组合关系,可以逐步构建出完整的解题思路。 ... [详细]
  • 优化后的标题:校园互联新方案:10397连接教育未来 ... [详细]
  • 深入解析 Android Drawable:第六阶段进阶指南 ... [详细]
  • CCCCGPLT L2005: 集合相似度计算的双指针算法优化 ... [详细]
  • 在探讨 AS3 中的数据深度复制技术时,本文详细介绍了实现数据深度克隆的有效方法。通过对比多种方案,最终确定了一种高效且可靠的实现方式,所有代码均来源于公开资源,确保了方法的实用性和可操作性。 ... [详细]
  • 在幼儿园中,有 \( n \) 个小朋友需要通过投票来决定是否午睡。尽管这个问题对每个孩子来说并不是特别重要,但他们仍然希望通过谦让的方式达成一致。每个人都有自己的偏好,但为了集体和谐,他们决定采用一种最小割的方法来解决这一问题。这种方法不仅能够确保每个人的意愿得到尽可能多的尊重,还能找到一个最优的解决方案,使整体满意度最大化。 ... [详细]
  • 在单个图表中实现饼图与条形图的精准对齐 ... [详细]
  • 利用Redis HyperLogLog高效统计微博日活跃和月活跃用户数
    本文探讨了如何利用Redis的HyperLogLog数据结构高效地统计微博平台的日活跃用户(DAU)和月活跃用户(MAU)数量。通过HyperLogLog的高精度和低内存消耗特性,可以实现对大规模用户数据的实时统计与分析,为平台运营提供有力的数据支持。 ... [详细]
  • 根据不同环境需求,利用 Vue CLI 的 `npm run build` 命令对项目进行定制化打包,如测试、预发布和生产环境。通过配置 `process.env` 变量,实现不同环境下接口和服务的动态切换,确保应用在各阶段都能高效运行和调试。 ... [详细]
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社区 版权所有