C++之Boost Asio相关

Boost Asio相关

Boost是一个C++可移植库,是对标准库的后备拓展,也是C++标准化进程的开发引擎之一。

Boost Asio是Boost库中的一个部分,Asio的全称为Asynchronous input and output(异步输入输出)的缩写。结合Boost的特点,Asio提供了一套和平台无关的异步数据处理能力,当然它也支持同步数据处理。

使用Asio只需要引入一个头文件即可。

#include<boost/asio.hpp>

对于所有使用Asio的程序,都必须包含至少包含一个io_service对象。对于Asio这个Boost库而言,它抽象了诸如网络、串口通信等等这些概念,并将其统一为规为IO操作,所以io_service这个类提供了访问了I/O的功能,因此使用Asio时,必须定义:

boost::asio::io_service io;

HTTP连接

既然网络相关概念已经被抽象成IO,我们就只需要关系从IO流中获取消息,因此我们本质上还是在进行IO流中获取消息,因此我们本质上还是在进行IO操作,只是这些操作需要具备一些基本的网络概念。

HTTP 和 HTTPS 的底层实际上是使用的 TCP 可靠连接,通过 Socket 技术进行通信,而一个 Socket 由 IP 地址及端口构成。无例外地,Asio 同样也需要建立一个和 socket 有关的对象,那就是 boost::asio::ip::tcp::socket。可想而知,Socket 既然是网络通信的基础,那么自然的我们要进行的 IO 操作也就必须在这里完成,因此,我们定义的 boost::asio::ip::tcp::socket 对象,必须由 io_service 来进行构造,即:

boost::asio::ip::tcp::socket socket(io)

有了 socket 对象是不够的。在网络通信中,网络 IO 就入口串口一样,是以流的方式进行的。所以这个 socket 对象只能用来做我们日后进行 IO 操作时的一个必要属性。

不难看出,一个普通的 boost::asio::ip::tcp::socket 对象,实际上就是一个 HTTP 的 Socket 连接,因此我们在日后进行代码编写时,甚至于可以使用 typedef 将这个类型直接定义为 HTTP:

typedef boost::asio::ip::tcp::socket HTTP;

然而,作为服务端,我们可能构建很多很多的连接从而响应并发,所以当我们需要建立连接时候,就需要使用一个叫做 acceptor 的对象。

而 boost::asio::ip::tcp::acceptor 从名字上就可以看出,这个对象应该被用于建立连接。在 Boost 中,我们需要初始化一个 acceptor 对象时,必须提供一个 io_service 对象和一个 endpoint 对象。

那么 endpoint 又是什么?事实上,socket 是一个端到端的连接,所谓 endpoint 就是 socket 位于服务端的一个端点,我们知道,socket 是由 IP 地址和端口号组成的,那么当我们需要为其建立一个 IPv4 的网络,首先可以建立一个 boost::asio::ip::tcp::endpoint 对象:

unsigned short port = 8080;

boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);

其中 boost::asio::ip::tcp::v4() 用于初始化一个 IPv4 的网络。最后在使用这个 endpoint 对象来初始化 acceptor:

boost::asio::ip::tcp::acceptor acceptor(io, endpoint);

至此,我们讨论了如何使用 Asio 建立一个普通的网络操作对象 acceptor,以及在进行普通 HTTP 网络操作时需要的 socket 对象。

HTTPS连接

讨论完了 Asio 里 HTTP 连接,我们再来看看 Asio 中的 HTTPS 是如何建立连接的。Asio 是一个开源的库,所以它也不可避免的在处理不擅长的逻辑时需要添加对别的框架的依赖。Asio 的 HTTPS 相关的 SSL 操作,就依赖了 OpenSSL 库。

要使用 SSL 相关的操作,还需要额外引入一个头文件:

#include <boost/asio/ssl.hpp>

我们在上一小节里讨论了 boost::asio::ip::tcp::socket 产生的 Socket 对象实际上就是普通的 HTTP 对象。对于 HTTPS 而言,实际上就是对这个 socket 所产生的通道进行一个一层封装和加密。在 Boost Asio 中,加密 socket 的方式就是使用 boost::asio::ssl::stream,并将 boost::asio::ip::tcp::socket 作为模板参数传入给这个对象,即:

typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> HTTPS;

而当我们要构造一个 HTTPS 的 socket 对象时,Boost Asio 要求必须为这个 socket 建立一个 boost::asio::ssl::context 对象。而一个 context 可以有很多不同的类型,最常用的,就是boost::asio::ssl::context::sslv23。构造好了 context 对象之后这还不够,因为一个 https 的服务器需要提供证书文件和秘钥文件,所以还需要使用 use_certificate_chain_file() 和 use_private_key_file() 这两个方法来进行进一步的配置:

context.use_certificate_chain_file(cert_file);

context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);

中的 boost::asio::ssl::context::pem 是指定的证书类型。因此相较于 HTTP 而言,HTTPS 的建立其实就是增加了对证书的配置、和 socket 加密的环节,对比如下:

// http

boost::asio::ip::tcp::socket http_socket(io);

// https

boost::asio::ssl::context context(boost::asio::ssl::context::sslv23);

context.use_certificate_chain_file(cert_file);

context.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);

boost::asio::ssl::stream<boost::asio::ip::tcp::socket> https_socket(io, context);

I/O操作

上面我们讨论了如何建立连接,现在我们再来看看如何进行 IO 操作。

当我们有了 socket 对象之后,就可以从里面读取网络流数据了。读取数据时,我们需要定义一个流缓冲 boost::asio::streambuf 对象,用于逐行读取 socket 中的数据:

boost::asio::streambuf read_buffer;

另外,很多网络协议其实都是基于行实现的,也就是说这些协议元素是由 \r\n 符号进行界定,HTTP 也不例外,所以在 Boost Asio 中,读取使用分隔符的协议,可以使用 async_read_untile() 方法:

boost::asio::async_read_until(socket, readbuffer, "\r\n\r\n", read_handler);

其中 socket 就是我们的 socket 连接,而 readbuffer 就是根据界定符读取到的一行数据,"\r\n\r\n" 就是分隔符,而对于 read_handler 我们还需要再进一步讨论。

read_handler 是一个无返回类型的函数对象,它接受两个参数,一个是 boost::system::error_code,另一个是 size_t(bytes_transferred):

void read_handler(
    const boost::system::error_code& ec,
    std::size_t bytes_transferred)

{
  ...
}

boost::system::error_code 用来描述操作是否成功,而 size_t bytes_transferred 则是用来确定接受到的字节数,通常情况下,我们可以用 std::bind 来将参数绑定到我们的某个函数传入,但实际上我们还有更好的做法,那就是 lambda 表达式,因为 Lambda 表达式还具有另外的一个功能,那就是进行值捕获,对于这一点,我们在后面实现框架的时候再详细讨论。

在这个 read_handler 中,我们实际上是在不断的读取 socket 里面的内容,因此我们还需要使用 boost::asio::async_read 对后面的内容进行进一步的读取,而它的用法 和 boost::asio::async_read_until 几乎一样,唯一的区别就是在 read_handler 这个参数之前,需要指定 读取的长度,通常我们可以使用 boost::asio::transfer_exactly 进行指定,故这里不再详细赘述,我们在后面实现框架的时候,再详细讨论。

最后,我们完成了读取的操作,就只剩下最后一步了,那就是服务器响应请求,回写请求的资源供给客户端,这时候我们就需要使用另一个方法:boost::asio::async_write。从名字上可以看出,这个方法和 boost::asio::async_read 属于同一个方法家族,可想而知用法也完全类似,我们还是留到后面的实际代码中再进行讨论。

原文地址:https://www.cnblogs.com/wanghao-boke/p/12242539.html

时间: 2024-10-10 10:09:35

C++之Boost Asio相关的相关文章

boost asio 接收数据异常 $/x1

说明 在发送PLAY指令之后,接收到的数据是$/x1,实际上通过调试服务器端,发现服务器端实际上已经了200 OK过来,因此猜测是接收超时,但是在前面的指令收发都没有问题,尝试在PLAY指令发送之后,接收之前调用Sleep函数睡眠500ms,没有任何的效果,查看如何设置socket超时,也没有相关资料,使用的都是同步的收发 测试代码 #include <iostream> #include <fstream> #include <string> #include <

boost.asio包装类st_asio_wrapper开发教程(一)

一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统: 二:st_asio_wrapper的特点效率高.跨平台.完全异步,当然这是从boost.asio继承而来:自动重连,数据透明传输,自动解决分包粘包问题(必须使用默认的打包解包器,这一特性表现得与udp一样):只支持tcp和udp协议: 三:st_asio_wrapper的大体结构st_asio_wrapper.h:编译器

boost::asio::io_service(之一)

boost::asio::io_service /// Provides core I/O functionality. /** * The io_service class provides the core I/O functionality for users of the * asynchronous I/O objects, including: * io_service类为下面的异步对象提供了核心的I/O操作函数 * * @li boost::asio::ip::tcp::socke

boost.asio包装类st_asio_wrapper开发教程(2014.5.23更新)(一)-----转

一:什么是st_asio_wrapper它是一个c/s网络编程框架,基于对boost.asio的包装(最低在boost-1.49.0上调试过),目的是快速的构建一个c/s系统:二:st_asio_wrapper的特点效率高.跨平台.完全异步,当然这是从boost.asio继承而来:自动重连,数据透明传输,自动解决分包粘包问题(必须使用默认的打包解包器,这一特性表现得与udp一样):只支持tcp和udp协议:三:st_asio_wrapper的大体结构st_asio_wrapper.h:编译器版本

客户端技术的一点思考(数据存储用SQLite, XMPP通讯用Gloox, Web交互用LibCurl, 数据打包用Protocol Buffer, socket通讯用boost asio)

今天看到CSDN上这么一篇< 彻底放弃没落的MFC,对新人的忠告!>, 作为一个一直在Windows上搞客户端开发的C++程序员,几年前也有过类似的隐忧(参见 落伍的感觉), 现在却有一些不同的想法. 首先,个人职业发展是否成功, 技术只是其中一小块,尤其是在大公司, 更多的是依靠所谓的软实力.作为一个对技术有追求的工匠,我们下面重点说技术相关的. 现在回头看计算机行业的发展,我们看到不同的发展阶段: 1. PC时代,这个时代离我们并不遥远, 也有是2000年前后, 该时代最鲜明的特征是Win

Boost.Asio技术文档

Christopher Kohlhoff Copyright ? 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENSE_1_0.txt文件或从http://www.boost.org/LICENSE_1_0.txt) Boost.Asio是用于网络和低层IO编程的跨平台C++库,为开发者提供了C++环境下稳定的异步模型. 综述 基本原理 应用程序与外界交互的方式有很多,可通过文件,网络,串口或控制台.例如在网络通信中,完

Boost Asio初探

一.简介 Boost Asio ( asynchronous input and output)关注数据的异步输入输出.Boost Asio 库提供了平台无关性的异步数据处理能力(当然它也支持同步数据处理).一般的数据传输过程需要通过函数的返回值来判断数据传输是否成功,而Boost Asio将数据传输分为两个独立的步骤: 采用异步任务的方式开始数据传输. 将传输结果通知调用端 与传统方式相比,它的优势在于程序在数据传输期间不会被阻塞. 二.I/O Services 与 I/O Objects 应

boost::asio译文

Christopher Kohlhoff Copyright © 2003-2012 Christopher M. Kohlhoff 以Boost1.0的软件授权进行发布(见附带的LICENSE_1_0.txt文件或从http://www.boost.org/LICENSE_1_0.txt) Boost.Asio是用于网络和低层IO编程的跨平台C++库,为开发者提供了C++环境下稳定的异步模型. 综述 基本原理 应用程序与外界交互的方式有很多,可通过文件,网络,串口或控制台.例如在网络通信中,完

Boost.Asio基础(四)

TCP vs UDP vs ICMP 如前所述,对于所有类型的socket,并不是都有同样的成员函数.下面的表格列出了3个socket中存在的成员函数: 名称 TCP UDP ICMP async_read_some Yes - - async_receive_from - Yes Yes async_write_some Yes - - async_send_to - Yes Yes read_some Yes - - receive_rom - Yes Yes write_some Yes