Asio网络库 学习笔记
Boost官网:https://www.boost.org/
Boost库 许可证:
// Copyright Joe Coder 2004 - 2006.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// https://www.boost.org/LICENSE_1_0.txt)
1. Asio简介
Asio是一个跨平台的C++网络库,它是Boost库的一部分,它是异步输入输出的核心。Asio提供了一组异步的I/O操作,包括TCP和UDP的socket、定时器、串口等。Asio的核心是一个事件循环,它使用epoll、kqueue、IOCP等系统调用来实现异步I/O操作。Asio的事件循环是单线程的,但是它提供了一些接口来实现多线程的异步操作。
这里引用文章Boost asio 官方教程简介的例子:异步任务的典型例子是网络应用。 如果数据被发送出去了,比如发送至 Internet,通常需要知道数据是否发送成功。 如果没有一个象 Boost.Asio 这样的库,就必须对函数的返回值进行求值。 但是,这样就要求待至所有数据发送完毕,并得到一个确认或是错误代码。 而使用 Boost.Asio,这个过程被分为两个单独的步骤:第一步是作为一个异步任务开始数据传输。 一旦传输完成,不论成功或是错误,应用程序都会在第二步中得到关于相应的结果通知。 主要的区别在于,应用程序无需阻塞至传输完成,而可以在这段时间里执行其它操作。
2. Asio的使用
2.1. Asio的安装
这里举例Unix/Linux 环境下的安装。
Asio是Boost库的一部分,所以要使用Asio,首先要安装Boost库。
-
下载Boost库
Boost库的下载地址:https://boostorg.jfrog.io/artifactory/main/release/
或者 https://sourceforge.net/projects/boost/files/首先我们创建一个目录,用来存放Boost库的源码和编译后的库文件。
# 进入用户目录 cd ~ # 创建Boost目录 mkdir Boost # 进入Boost目录 cd Boost
然后下载Boost库的源码,这里下载的是Boost 1.83.0版本的源码。
wget https://boostorg.jfrog.io/artifactory/main/release/1.83.0/source/boost_1_83_0.tar.gz
国内下载可能有点慢。建议用第二个网站。
-
解压Boost库
tar -zxvf boost_1_83_0.tar.gz
-
编译Boost库
cd boost_1_83_0 ./bootstrap.sh ./b2
编译完成后,会有如下提示:
The Boost C++ Libraries were successfully built! The following directory should be added to compiler include paths: /home/username/boost/boost_1_83_0 The following directory should be added to linker library paths: /home/username/boost/boost_1_83_0/stage/lib
这里的username是你的用户名。
-
安装Boost库
sudo ./b2 install
注意,由于Asio库使用了C++11的特性,所以编译时最好要加上-std=c++11
选项,并且Asio使用了thread进行异步操作,所以编译时要加上-pthread
选项。
3. Asio工作原理
这里主要参考Asio官方文档。
对于asio库,程序至少要包含一个io_context对象,这个对象代表程序链接到操作系统的I/O服务。io_context对象提供了一种将事件处理程序与操作系统的I/O服务进行交互的方法。boost::asio::io_contextboost::asio::thread_poolboost::asio::system_context
boost::asio::io_context io_context;
执行I/O操作都需要一个I/O对象,比如socket、定时器、串口等。
boost::asio::ip::tcp::socket socket(io_context);
有两种类型的I/O操作:同步操作和异步操作。同步操作会阻塞当前线程,直到操作完成。异步操作会在操作完成后调用一个事件处理程序。
对于同步操作:
-
程序在开始阶段需要连接I/O对象。
socket.connect(server_endpoint);
-
I/O对象将请求转发到io_context对象。
-
io_context对象调用操作系统来执行连接操作。
-
操作系统将操作结果返回到io_context对象。
-
io_context对象将操作产生的任何错误转换为类型的对象。可以将与特定值进行比较,也可以作为布尔值进行测试(其中结果表示没有发生错误)。然后将结果转发回I/O对象。
boost::system::error_codeerror_codefalse
-
如果操作失败,I/O对象将引发一个类型的异常。如果启动操作的代码改为:
boost::system::system_error
boost::system::error_code ec; socket.connect(server_endpoint, ec);
然后将变量设置为操作的结果,并且不会引发异常。error_codeec
对于异步操作:
-
您的程序通过调用I/O对象来启动连接操作:
socket.async_connect(server_endpoint, your_completion_handler);
其中是具有签名的函数或函数对象:
your_completion_handler
void your_completion_handler(const boost::system::error_code& ec);
所需的确切签名取决于正在执行的异步操作。
-
I/O对象将请求转发到io_context对象。
-
io_context对象向操作系统发出信号,表示它应该启动异步连接。
等待(在同步情况下,此等待将完全包含在连接操作的持续时间内。)
(官方文档里给的词是 Time passes. 个人认为其含义是io_context对象等待系统响应。按我个人的理解:此时系统并不会立即响应请求,而是将请求放入队列,按照系统调度响应。此时io_context对象可以进行其他操作,也可以进行等待。)
- 操作系统通过将结果放在队列中来指示连接操作已经完成,该队列准备由io_context对象拾取。
- 当使用作io_context对象时,程序必须调用(或调用类似的成员函数之一)才能检索结果。在有未完成的异步操作时对块的调用,因此通常在启动第一个异步操作后立即调用它。
io_contextio_context::run()io_contextio_context::run()
- 在对的调用中,I/O执行上下文将操作的结果排成队列,将其转换为,然后将其传递给您的完成处理程序。
io_context::run()error_code
4. Asio的使用
4.1 简单使用
下面这个程序用来实现一个简单的UDP广播。
#include <iostream>
#include <boost/asio.hpp>
int main() {
try {
boost::asio::io_service io_service; // 创建io_service对象
boost::asio::ip::udp::socket socket(io_service); // 创建socket对象
// 设置广播地址和端口
boost::asio::ip::udp::endpoint broadcast_endpoint(
boost::asio::ip::address::from_string("255.255.255.255"), 50001);
// 开启广播选项
socket.open(boost::asio::ip::udp::v4()); // 打开套接字
socket.set_option(boost::asio::socket_base::broadcast(true)); // 设置广播选项
// 绑定套接字到本地端口
boost::asio::ip::udp::endpoint local_endpoint(
boost::asio::ip::address::from_string("0.0.0.0"), 0);
socket.bind(local_endpoint); // 绑定套接字到本地端口
std::string message = "Hello, UDP Broadcast!";
socket.send_to(boost::asio::buffer(message), broadcast_endpoint); // 发送广播消息
std::cout << "Sent message: " << message << std::endl;
} catch (std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
}
return 0;
}
标签:Asio,asio,io,Boost,笔记,context,boost
From: https://www.cnblogs.com/BryceAi/p/17689249.html