boost之asio
asio
asio是C++的准标准网络库,并且C++20标准库的网络部分将基于ASIO,需引入头文件#include <boost/asio.hpp>
。
ip地址
boost定义了表示ip地址的类型,支持ipv4和ipv6,提供ip::address
和ip::address_v4
以及ip::address_v6
三种类型。
- 通过字符串构造ip地址:
#include <boost/asio.hpp>
namespace ba = boost::asio;
namespace bi = ba::ip;
int main(int argc, char* argv[])
{
// 通过点分十进制转换为ipv4地址
bi::address addrV4 = bi::make_address("127.0.0.1");
assert(addrV4.is_v4());
// 通过十六进制转换为ipv6地址
bi::address addrV6 = bi::make_address("ABCD:EF01:2345:6789:ABCD:EF01:2345:6789");
assert(addrV6.is_v6());
// bi::address重载了流操作符,可以直接输出(所以也可以用boost::lexical_cast<string>(address))
std::cout << addrV4 << std::endl;
std::cout << addrV6 << std::endl;
return 0;
}
ip地址+端口
对于tcp和udp两种协议,定义了对应的类型:ip::tcp::endpoint
和ip::udp::endpoint
:
- 通过ip地址和端口号构造
int main(int argc, char* argv[])
{
// 端口号直接传入就行,不用转换为网络序
bi::tcp::endpoint ep(bi::make_address("127.0.0.1"), 1234);
// endpoint也重载了流操作符
std::cout << ep << std::endl;
return 0;
}
域名解析
asio中提供ip::tcp::resolver
和ip::udp::resolver
实现域名解析,相当于unix网络编程中的getaddrinfo()接口封装:
- 解析指定域名和端口对应的ip地址和端口信息:
int main(int argc, char* argv[])
{
// 域名解析需要使用底层网络io
ba::io_context io;
bi::tcp::resolver resolver(io);
// 对baidu域名进行解析
auto endpoints = resolver.resolve("www.baidu.com", "https");
for (auto& endpoint : endpoints) {
std::cout << endpoint.endpoint() << std::endl;
}
return 0;
}
定时器
同步模式:
int main(int argc, char const *argv[])
{
ba::io_context io;
ba::steady_timer tm (io, ba::chrono::seconds(5));
std::cout << "start timer" << std::endl;
tm.wait();
std::cout << "end wait" << std::endl;
return 0;
}
异步模式:
int main(int argc, char const *argv[])
{
ba::io_context io;
ba::steady_timer tm (io, ba::chrono::seconds(5));
tm.async_wait([] (boost::system::error_code ec) {
std::cout << "time's up" << std::endl;
});
io.run();
return 0;
}
周期定时器:
void heartbeat(std::shared_ptr<ba::steady_timer> tm, boost::system::error_code ec) {
std::cout << "heart beat" << std::endl;
tm->expires_after(ba::chrono::seconds(1));
tm->async_wait([tm] (boost::system::error_code ec) {
heartbeat(tm, ec);
});
}
int main(int argc, char const *argv[])
{
ba::io_context io;
auto tm = std::make_shared<ba::steady_timer>(io, ba::chrono::seconds(1));
tm->async_wait([tm] (boost::system::error_code ec) {
heartbeat(tm, ec);
});
io.run();
return 0;
}
buffer
asio使用的是proactor
模式,也就是io操作不光是通知有了可读可写事件,并且会将可读写到调用者指定的buffer
中,从调用者指定的buffer
中取数据写入,所以asio提供了数据缓冲类型。
有两种buffer:mutable_buffer
和const_buffer
,buffer并不申请内存,它只是一个内存块的封装,本质上就一个void *data,size_t size
的一个数据对,所以需要确保引用数据的生命周期。
buffer
函数用于创建mutable_buffer
和const_buffer
对象,支持POD数组,PODarray
,PODvector
,string
类型:
#include <iostream>
#include <string>
#include <boost/asio.hpp>
namespace ba = boost::asio;
int main(int argc, char const *argv[])
{
(void)argc;
(void)argv;
std::string str = "123";
ba::mutable_buffer mbuf = ba::buffer(str);
const std::string cstr = "123";
ba::const_buffer cbuf = ba::buffer(cstr);
std::cout << mbuf.size() << std::endl;
std::cout << cbuf.size() << std::endl;
return 0;
}
同步模式tcp客户端和服务端
以下是asio教程中关于daytime服务的tcp客户端和服务端代码:
#include <iostream>
#include <string>
#include <array>
#include <boost/asio.hpp>
namespace ba = boost::asio;
namespace bi = ba::ip;
int main(int argc, char const *argv[])
{
(void)argc;
(void)argv;
ba::io_context io;
bi::tcp::resolver resolver(io);
auto endpoints = resolver.resolve("localhost", "daytime");
bi::tcp::socket connSocket(io);
ba::connect(connSocket, endpoints);
std::array<char, 128> arr;
while (true) {
boost::system::error_code ec;
size_t len = connSocket.read_some(ba::buffer(arr), ec);
if (ba::error::eof == ec) {
break;
} else if (ec) {
throw boost::system::system_error(ec);
}
std::cout.write(arr.data(), len);
}
return 0;
}
#include <iostream>
#include <string>
#include <array>
#include <ctime>
#include <boost/asio.hpp>
namespace ba = boost::asio;
namespace bi = ba::ip;
int main(int argc, char const *argv[])
{
(void)argc;
(void)argv;
ba::io_context io;
bi::tcp::acceptor acceptor(io, bi::tcp::endpoint(bi::tcp::v4(), 13));
while (true) {
bi::tcp::socket connSocket(io);
acceptor.accept(connSocket);
time_t now = time(0);
std::string message = ctime(&now);
ba::write(connSocket, ba::buffer(message));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)