C++ asio网络编程(2)buffer结构

目录

关于buffer

常用asio::buffer函数创建一个缓冲区

Buffer的使用(比较麻烦的版本和方便的版本对比)

创建缓冲区示例

注意:static_cast(buf.get())这部分代码将buf指针转换为void * 类型 为什么要这么做?*>


在Boost的asio里,发送数据需要用一个结构去承载,这个结构就是buffer。

关于buffer

任何网络库都有提供buffer的数据结构,所谓buffer就是接收和发送数据时缓存数据的结构。

在 Boost.Asio 中,发送和接收数据时需要使用 buffer 来承载数据。Buffer 可以被理解为用于缓存数据的结构,而在 Boost.Asio 中提供了 asio::mutable_bufferasio::const_buffer 这两个结构。

  • asio::mutable_buffer 用于写操作,表示可以修改数据的缓冲区。
  • asio::const_buffer 用于读操作,表示只读数据的缓冲区。

这两个结构都代表一段连续的内存空间,首字节存储了后续数据的长度。虽然这两个结构不直接用于 Asio API,但它们是构成 MutableBufferSequenceConstBufferSequence 的基本单元。

MutableBufferSequenceConstBufferSequence 是由多个 asio::mutable_bufferasio::const_buffer 组成的结构,它们分别用于向 Asio API 提供可写入数据和只读数据的参数。可以理解为 MutableBufferSequence 的数据结构类似于 std::vector<asio::mutable_buffer>。这样的设计可以节省空间并且更好地适应异步 I/O 操作的需求。

因此,在 Boost.Asio 中,我们可以使用 asio::mutable_bufferasio::const_buffer 来创建单个的可写入或只读的缓冲区,并将它们组合成 MutableBufferSequenceConstBufferSequence 以便作为参数传递给 Asio API 来进行数据的发送和接收操作。

结构如下:

Boost.Asio 提供了 buffer() 函数来简化用户对缓冲区的处理。该函数接受多种形式的字节流作为参数,并返回适配了 MutableBufferSequenceConstBufferSequence 概念的对象,即 asio::mutable_buffers_1asio::const_buffers_1 类型对象。

  • 如果传递给 buffer() 函数的参数是只读类型,则函数返回 asio::const_buffers_1 类型对象。
  • 如果传递给 buffer() 函数的参数是可写类型,则返回 asio::mutable_buffers_1 类型对象。

asio::const_buffers_1asio::mutable_buffers_1 提供了符合 ConstBufferSequenceMutableBufferSequence 概念的接口,因此它们可以直接作为 Boost.Asio API 函数的参数使用。

简而言之,使用 buffer() 函数可以轻松地生成符合要求的缓冲区对象,使得用户在发送和接收数据时更加方便。

常用asio::buffer函数创建一个缓冲区

在Boost.Asio库中,asio::buffer函数通常有两个重载版本:

  1. 第一个参数是指向数据的指针,第二个参数是数据的大小。这种情况下,asio::buffer会创建一个用于表示该数据的缓冲区对象。

  2. 第一个参数是数据结构或容器,第二个参数是数据的大小。这种情况下,asio::buffer会创建一个用于表示数据结构或容器中的数据的缓冲区对象。

Buffer的使用(比较麻烦的版本和方便的版本对比)

这个是比较麻烦的版本,还需要将原来的字符串构造成asio::const_buffer才能使用

//buffer的使用(比较麻烦的版本)
void use_const_buffer() {
	std::string buf = "Hello World";
	asio::const_buffer asio_buf(buf.c_str(), buf.length());
	//构造出一个const_buffer
	std::vector<asio::const_buffer> buffers_sequence;
	buffers_sequence.push_back(asio_buf);
}

下面是比较简单的版本,可以看到与上面相对比非常的简洁

void use_buffer_str() {
	asio::const_buffers_1 output_buf = asio::buffer("Hello World");
	//该行是上一个函数的简化版,这个output_buf可直接作为参数传给asio的api作为数据缓存的一种结构来使用
}

创建缓冲区示例

//创建一个20字节大小的用于输入操作的缓冲区,该缓冲区包含了由buf指向的数据
void use_buffer_array() {
	const size_t BUF_SIZE_BYTES = 20;
	std::unique_ptr<char[]> buf(new char[BUF_SIZE_BYTES]);
	//括号内为默认构造,申请一块char类型的内存地址,使其由unique_ptr类型智能指针buf接管

	auto input_buf = asio::buffer(static_cast<void*>(buf.get()),BUF_SIZE_BYTES);
	//这行代码是使用Boost.Asio库中的函数来创建一个用于输入操作的缓冲区。
	//asio::buffer是Boost.Asio库中的一个函数,用于创建一个表示特定内存区域的缓冲区对象,以便进行异步I / O操作。
	//static_cast<void*>(buf.get())这部分代码将buf指针转换为void * 类型,
	//这样做是为了确保缓冲区能够被正确地传递给asio::buffer函数。这里假设buf是一个指向某种数据类型的指针。
	//BUF_SIZE_BYTES是一个表示缓冲区大小的常量,它指定了要传输的数据的大小。
	//综合起来,这行代码的作用是创建一个用于输入操作的缓冲区,该缓冲区包含了指向buf指针所指向的数据,
	//并且数据的大小由BUF_SIZE_BYTES指定。这通常用于异步I / O操作,比如网络通信或文件读写等场景。
}

注意:static_cast<void*>(buf.get())这部分代码将buf指针转换为void * 类型 为什么要这么做?

在这里,使用 static_cast<void*>(buf.get())buf 指针转换为 void* 类型的原因是为了将 buf 智能指针所管理的内存地址传递给 asio::buffer 函数。Boost.Asio库中的 asio::buffer 函数通常期望接收一个指向内存区域的 void* 类型指针以及数据的大小来创建缓冲区对象。

由于 buf 是一个 std::unique_ptr 类型的智能指针,直接将其传递给 asio::buffer 可能会导致类型不匹配的问题,因为 asio::buffer 期望的是一个 void* 类型的指针。因此,使用 static_cast<void*>(buf.get())buf 指针转换为 void* 类型,以便符合函数的参数要求。

总之,这样做是为了确保能够将 buf 所管理的内存地址正确地传递给 asio::buffer 函数,并且提供符合要求的指针类型。

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一个简单的例子。 首先,您需要安装 crow 和 asio 库。您可以使用以下命令来安装它们: ``` $ sudo apt-get install libasio-dev $ git clone https://github.com/ipkn/crow.git $ cd crow $ make ``` 接下来,您可以创建一个名为 `webserver.cpp` 的文件,并将以下代码复制粘贴到该文件中: ```c++ #include "crow.h" #include <iostream> int main() { crow::SimpleApp app; CROW_ROUTE(app, "/") ([](){ return "Hello world!"; }); app.port(18080).run(); } ``` 这个应用程序将创建一个基本的 web 服务器,它将监听端口 18080,并在收到请求时返回 "Hello world!"。 现在,让我们来看看如何使用 asio 来实现网络编程。我们将使用 asio 来创建一个 TCP 客户端,该客户端将连接到远程服务器并发送一条消息。 在 `webserver.cpp` 文件的顶部添加以下代码: ```c++ #include <asio.hpp> #include <string> ``` 然后,在 `main` 函数中添加以下代码: ```c++ // 创建一个 io_service 对象 asio::io_service io_service; // 创建一个 TCP resolver 对象,并解析远程主机和端口 asio::ip::tcp::resolver resolver(io_service); asio::ip::tcp::resolver::query query("www.example.com", "80"); auto endpoints = resolver.resolve(query); // 创建一个 TCP socket 对象,并连接到远程主机 asio::ip::tcp::socket socket(io_service); asio::connect(socket, endpoints); // 发送消息到远程主机 std::string message = "GET / HTTP/1.1\r\nHost: www.example.com\r\n\r\n"; asio::write(socket, asio::buffer(message)); ``` 这个代码片段将创建一个 `io_service` 对象,并使用 `resolver` 和 `socket` 对象来连接到远程主机。然后,它将发送一条消息到远程主机。 现在,您可以编译并运行代码。在终端中,导航到 `webserver.cpp` 文件所在的目录,并执行以下命令: ``` $ g++ -std=c++11 webserver.cpp -o webserver -lboost_system -lpthread $ ./webserver ``` 这将编译并运行您的应用程序。现在,您可以在浏览器中打开 `http://localhost:18080` 来查看您的 web 服务器是否正常工作,并在终端中查看输出以查看来自远程服务器的响应。 希望这可以帮助您入门 crow 和 asio

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值