教程(二):Boost.Asio 网络编程入门(TCP/UDP 服务器与客户端)
Boost 库教程!本篇是 C++ Boost 库教程(二):Boost.Asio 网络编程入门(TCP/UDP 服务器与客户端),旨在帮助您掌握 Boost.Asio 的基础网络编程,重点实现 TCP 和 UDP 服务器与客户端的开发。结合您之前的上下文(尝试编译 Boost 1.88.0 的 64 位调试版静态库 libboost_system-vc143-mt-gd-x64-1_88.lib 和 libboost_log-vc143-mt-gd-x64-1_88.lib 未成功,使用 Visual Studio 2022,目标为 64 位静态库,最新信息显示仍在 x86 编译器环境),本教程将假设您已解决编译问题(若未解决,我会在文末提供进一步排查步骤),并提供完整的代码示例、编译命令和测试方法,确保您能快速上手 Boost.Asio 开发 TCP/UDP 调试工具。内容以中文呈现,结构清晰,适合初学者到中高级开发者。
C++ Boost 库教程(二):Boost.Asio 网络编程入门(TCP/UDP 服务器与客户端)
0. 写在前面的话
Boost.Asio 是 Boost 库中最强大的组件之一,用于异步 I/O 操作,特别适合网络编程(如 TCP、UDP、SSL)以及低级 I/O(如文件、串口)。它提供了跨平台、高性能的网络通信解决方案,广泛应用于服务器开发、实时通信和调试工具。Boost.Asio 的设计基于 异步回调 和 现代 C++ 特性(如 C++20 协程),支持单线程和多线程模型,灵活且高效。
在本教程中,我们将:
-
介绍 Boost.Asio 的核心概念。
-
实现简单的 TCP 服务器与客户端,支持消息回显。
-
实现简单的 UDP 服务器与客户端,支持广播消息。
-
使用 Boost.Log 记录通信日志,方便调试。
-
提供 Visual Studio 2022 的配置和编译步骤,针对 64 位调试版静态库。
-
附带测试方法和常见问题解答。
结合您的问题(开发 TCP/UDP 调试工具,需 Boost.System 和 Boost.Log),本教程将特别优化代码以匹配您的需求,确保代码简洁且可运行。若您仍未生成所需的 Boost 库,我会在文末提供针对性解决方案。
1. Boost.Asio 简介
1.1 什么是 Boost.Asio?
Boost.Asio(Asynchronous Input/Output)是一个跨平台的 C++ 库,用于处理异步 I/O 操作,包括:
-
网络通信:TCP、UDP、ICMP、WebSocket(通过 Boost.Beast)。
-
低级 I/O:文件、管道、串口。
-
定时器:定时任务和超时处理。
-
信号处理:捕获 SIGINT 等系统信号。
Boost.Asio 的核心特点:
-
异步模型:支持回调、协程(C++20)、Future/Promise。
-
高性能:基于操作系统的异步 I/O(如 Windows 的 IOCP、Linux 的 epoll)。
-
跨平台:支持 Windows、Linux、macOS。
-
依赖性:依赖 Boost.System(提供错误码处理)。
1.2 核心概念
-
io_context:Asio 的核心事件循环,管理所有异步操作。
-
socket:表示网络连接(如 TCP 或 UDP 套接字)。
-
acceptor:用于 TCP 服务器,监听并接受客户端连接。
-
resolver:解析主机名和端口(如 localhost:8888)。
-
buffer:管理读写数据的缓冲区(如 asio::buffer)。
-
error_code:处理操作错误(来自 Boost.System)。
1.3 与您的问题相关
-
Boost.System:libboost_system-vc143-mt-gd-x64-1_88.lib 是 Boost.Asio 的依赖,用于错误处理。
-
Boost.Log:libboost_log-vc143-mt-gd-x64-1_88.lib 用于记录通信日志,适合您的调试工具。
-
本教程的代码将使用这两个库,并提供 Visual Studio 2022 的 64 位调试版配置。
2. TCP 服务器与客户端实现
2.1 功能
-
TCP 服务器:监听端口 8888,接受客户端连接,接收消息并回显。
-
TCP 客户端:连接服务器,发送消息并接收回显。
-
日志:使用 Boost.Log 记录连接、消息和错误。
2.2 TCP 服务器代码:tcp_server.cpp
cpp
#include <boost/asio.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <iostream>
#include <memory>
#include <string>
namespace asio = boost::asio;
using asio::ip::tcp;
// 初始化日志
void init_logging() {
boost::log::add_file_log("tcp_server.log", boost::log::keywords::auto_flush = true);
boost::log::add_common_attributes();
}
class TcpSession : public std::enable_shared_from_this<TcpSession> {
public:
TcpSession(asio::io_context& io_context) : socket_(io_context) {}
tcp::socket& socket() { return socket_; }
void start() {
socket_.async_read_some(asio::buffer(buffer_),
[this, self = shared_from_this()](const boost::system::error_code& error, size_t bytes_transferred) {
if (!error) {
std::string message(buffer_.data(), bytes_transferred);
BOOST_LOG_TRIVIAL(info) << "Received: " << message;
std::string response = "Echo: " + message;
socket_.async_write_some(asio::buffer(response),
[self](const boost::system::error_code& error, size_t) {
if (!error) {
self->start(); // 继续读取
} else {
BOOST_LOG_TRIVIAL(error) << "Write error: " << error.message();
}
});
} else {
BOOST_LOG_TRIVIAL(error) << "Read error: " << error.message();
}
});
}
private:
tcp::socket socket_;
std::array<char, 1024> buffer_;
};
class TcpServer {
public:
TcpServer(asio::io_context& io_context, unsigned short port)
: acceptor_(io_context, tcp::endpoint(tcp::v4(), port)) {
start_accept();
}
private:
void start_accept() {
auto session = std::make_shared<TcpSession>(acceptor_.get_executor().context());
acceptor_.async_accept(session->socket(),
[this, session](const boost::system::error_code& error) {
if (!error) {
BOOST_LOG_TRIVIAL(info) << "Accepted connection from " << session->socket().remote_endpoint();
session->start();
} else {
BOOST_LOG_TRIVIAL(error) << "Accept error: " << error.message();
}
start_accept();
});
}
tcp::acceptor acceptor_;
};
int main() {
try {
init_logging();
asio::io_context io_context;
TcpServer server(io_context, 8888);
BOOST_LOG_TRIVIAL(info) << "TCP server started on port 8888";
io_context.run();
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what();
}
return 0;
}
2.3 TCP 客户端代码:tcp_client.cpp
cpp
#include <boost/asio.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
using asio::ip::tcp;
void init_logging() {
boost::log::add_file_log("tcp_client.log", boost::log::keywords::auto_flush = true);
boost::log::add_common_attributes();
}
int main(int argc, char* argv[]) {
try {
init_logging();
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " <host> <port>\n";
return 1;
}
asio::io_context io_context;
tcp::resolver resolver(io_context);
auto endpoints = resolver.resolve(argv[1], argv[2]);
tcp::socket socket(io_context);
asio::connect(socket, endpoints);
BOOST_LOG_TRIVIAL(info) << "Connected to " << argv[1] << ":" << argv[2];
std::string message = "Hello, Server!";
asio::write(socket, asio::buffer(message));
BOOST_LOG_TRIVIAL(info) << "Sent: " << message;
std::array<char, 1024> buffer;
boost::system::error_code error;
size_t len = socket.read_some(asio::buffer(buffer), error);
if (!error) {
std::string response(buffer.data(), len);
BOOST_LOG_TRIVIAL(info) << "Received: " << response;
} else {
BOOST_LOG_TRIVIAL(error) << "Read error: " << error.message();
}
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what();
}
return 0;
}
2.4 编译与运行
-
编译环境:
-
确保使用“VS 2022 的 x64 本机工具命令提示符”:
bash
cl-
输出:Microsoft (R) C/C++ Optimizing Compiler Version 19.43.34808 for x64。
-
-
确保 Boost 1.88.0 已编译,C:\boost_1_88_0\stage\lib 包含:
-
libboost_system-vc143-mt-gd-x64-1_88.lib
-
libboost_log-vc143-mt-gd-x64-1_88.lib
-
libboost_thread-vc143-mt-gd-x64-1_88.lib
-
libboost_date_time-vc143-mt-gd-x64-1_88.lib
-
libboost_filesystem-vc143-mt-gd-x64-1_88.lib
-
libboost_regex-vc143-mt-gd-x64-1_88.lib
-
-
-
编译 TCP 服务器:
bash
cl tcp_server.cpp /I "C:\boost_1_88_0" /link /LIBPATH:"C:\boost_1_88_0\stage\lib" libboost_system-vc143-mt-gd-x64-1_88.lib libboost_log-vc143-mt-gd-x64-1_88.lib libboost_thread-vc143-mt-gd-x64-1_88.lib libboost_date_time-vc143-mt-gd-x64-1_88.lib libboost_filesystem-vc143-mt-gd-x64-1_88.lib libboost_regex-vc143-mt-gd-x64-1_88.lib /MTd -
编译 TCP 客户端:
bash
cl tcp_client.cpp /I "C:\boost_1_88_0" /link /LIBPATH:"C:\boost_1_88_0\stage\lib" libboost_system-vc143-mt-gd-x64-1_88.lib libboost_log-vc143-mt-gd-x64-1_88.lib libboost_thread-vc143-mt-gd-x64-1_88.lib libboost_date_time-vc143-mt-gd-x64-1_88.lib libboost_filesystem-vc143-mt-gd-x64-1_88.lib libboost_regex-vc143-mt-gd-x64-1_88.lib /MTd -
运行:
-
启动服务器:
bash
.\tcp_server.exe -
启动客户端:
bash
.\tcp_client.exe 127.0.0.1 8888
-
-
测试:
-
客户端发送“Hello, Server!”,服务器回显“Echo: Hello, Server!”。
-
检查日志:
-
tcp_server.log:
[2025-06-09 19:30:00.123] [info] TCP server started on port 8888 [2025-06-09 19:30:05.456] [info] Accepted connection from 127.0.0.1:12345 [2025-06-09 19:30:05.789] [info] Received: Hello, Server! -
tcp_client.log:
[2025-06-09 19:30:05.456] [info] Connected to 127.0.0.1:8888 [2025-06-09 19:30:05.789] [info] Sent: Hello, Server! [2025-06-09 19:30:05.790] [info] Received: Echo: Hello, Server!
-
-
3. UDP 服务器与客户端实现
3.1 功能
-
UDP 服务器:监听端口 8889,接收消息并返回当前时间。
-
UDP 客户端:发送消息并接收服务器响应。
-
日志:使用 Boost.Log 记录通信细节。
3.2 UDP 服务器代码:udp_server.cpp
cpp
#include <boost/asio.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
using asio::ip::udp;
void init_logging() {
boost::log::add_file_log("udp_server.log", boost::log::keywords::auto_flush = true);
boost::log::add_common_attributes();
}
class UdpServer {
public:
UdpServer(asio::io_context& io_context, unsigned short port)
: socket_(io_context, udp::endpoint(udp::v4(), port)) {
socket_.set_option(asio::socket_base::broadcast(true));
start_receive();
}
private:
void start_receive() {
socket_.async_receive_from(asio::buffer(buffer_), remote_endpoint_,
[this](const boost::system::error_code& error, size_t bytes_transferred) {
if (!error) {
std::string message(buffer_.data(), bytes_transferred);
BOOST_LOG_TRIVIAL(info) << "Received from " << remote_endpoint_ << ": " << message;
std::string response = "Time: " + std::to_string(std::time(nullptr));
socket_.async_send_to(asio::buffer(response), remote_endpoint_,
[](const boost::system::error_code& error, size_t) {
if (error) {
BOOST_LOG_TRIVIAL(error) << "Send error: " << error.message();
}
});
} else {
BOOST_LOG_TRIVIAL(error) << "Receive error: " << error.message();
}
start_receive();
});
}
udp::socket socket_;
udp::endpoint remote_endpoint_;
std::array<char, 1024> buffer_;
};
int main() {
try {
init_logging();
asio::io_context io_context;
UdpServer server(io_context, 8889);
BOOST_LOG_TRIVIAL(info) << "UDP server started on port 8889";
io_context.run();
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what();
}
return 0;
}
3.3 UDP 客户端代码:udp_client.cpp
cpp
#include <boost/asio.hpp>
#include <boost/log/trivial.hpp>
#include <boost/log/utility/setup/file.hpp>
#include <boost/log/utility/setup/common_attributes.hpp>
#include <iostream>
#include <string>
namespace asio = boost::asio;
using asio::ip::udp;
void init_logging() {
boost::log::add_file_log("udp_client.log", boost::log::keywords::auto_flush = true);
boost::log::add_common_attributes();
}
int main(int argc, char* argv[]) {
try {
init_logging();
if (argc != 3) {
std::cerr << "Usage: " << argv[0] << " <host> <port>\n";
return 1;
}
asio::io_context io_context;
udp::resolver resolver(io_context);
auto endpoints = resolver.resolve(argv[1], argv[2]);
udp::socket socket(io_context, udp::endpoint(udp::v4(), 0));
std::string message = "Hello, UDP Server!";
socket.send_to(asio::buffer(message), *endpoints.begin());
BOOST_LOG_TRIVIAL(info) << "Sent to " << argv[1] << ":" << argv[2] << ": " << message;
std::array<char, 1024> buffer;
udp::endpoint sender_endpoint;
size_t len = socket.receive_from(asio::buffer(buffer), sender_endpoint);
std::string response(buffer.data(), len);
BOOST_LOG_TRIVIAL(info) << "Received from " << sender_endpoint << ": " << response;
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "Exception: " << e.what();
}
return 0;
}
3.4 编译与运行
-
编译 UDP 服务器:
bash
cl udp_server.cpp /I "C:\boost_1_88_0" /link /LIBPATH:"C:\boost_1_88_0\stage\lib" libboost_system-vc143-mt-gd-x64-1_88.lib libboost_log-vc143-mt-gd-x64-1_88.lib libboost_thread-vc143-mt-gd-x64-1_88.lib libboost_date_time-vc143-mt-gd-x64-1_88.lib libboost_filesystem-vc143-mt-gd-x64-1_88.lib libboost_regex-vc143-mt-gd-x64-1_88.lib /MTd -
编译 UDP 客户端:
bash
cl udp_client.cpp /I "C:\boost_1_88_0" /link /LIBPATH:"C:\boost_1_88_0\stage\lib" libboost_system-vc143-mt-gd-x64-1_88.lib libboost_log-vc143-mt-gd-x64-1_88.lib libboost_thread-vc143-mt-gd-x64-1_88.lib libboost_date_time-vc143-mt-gd-x64-1_88.lib libboost_filesystem-vc143-mt-gd-x64-1_88.lib libboost_regex-vc143-mt-gd-x64-1_88.lib /MTd -
运行:
-
启动服务器:
bash
.\udp_server.exe -
启动客户端:
bash
.\udp_client.exe 127.0.0.1 8889
-
-
测试:
-
客户端发送“Hello, UDP Server!”,服务器返回当前时间。
-
检查日志:
-
udp_server.log:
[2025-06-09 19:35:00.123] [info] UDP server started on port 8889 [2025-06-09 19:35:05.456] [info] Received from 127.0.0.1:12345: Hello, UDP Server! -
udp_client.log:
[2025-06-09 19:35:05.456] [info] Sent to 127.0.0.1:8889: Hello, UDP Server! [2025-06-09 19:35:05.789] [info] Received from 127.0.0.1:8889: Time: 1623248105
-
-
4. Visual Studio 项目配置
若您更倾向于使用 Visual Studio IDE 开发,以下是项目配置步骤:
-
创建项目:
-
在 Visual Studio 2022 创建“空项目(C++)”,命名为 AsioDemo。
-
设置平台为 x64。
-
-
添加源文件:
-
将 tcp_server.cpp、tcp_client.cpp、udp_server.cpp、udp_client.cpp 添加到项目。
-
-
设置包含路径:
-
项目属性 > C/C++ > 常规 > 附加包含目录:
C:\boost_1_88_0
-
-
设置库路径:
-
项目属性 > 链接器 > 常规 > 附加库目录:
C:\boost_1_88_0\stage\lib
-
-
设置运行时库:
-
项目属性 > C/C++ > 代码生成 > 运行时库:
-
调试模式:/MTd。
-
-
-
添加依赖库:
-
项目属性 > 链接器 > 输入 > 附加依赖项:
libboost_system-vc143-mt-gd-x64-1_88.lib libboost_log-vc143-mt-gd-x64-1_88.lib libboost_thread-vc143-mt-gd-x64-1_88.lib libboost_date_time-vc143-mt-gd-x64-1_88.lib libboost_filesystem-vc143-mt-gd-x64-1_88.lib libboost_regex-vc143-mt-gd-x64-1_88.lib
-
-
预处理器定义:
-
项目属性 > C/C++ > 预处理器 > 预处理器定义:
BOOST_LOG_DYN_LINK=0 BOOST_ALL_NO_LIB=0
-
-
编译与运行:
-
按 F5 运行,或在调试模式下运行服务器和客户端。
-
5. 常见问题与优化建议
5.1 常见问题
-
链接错误:无法解析的外部符号:
-
确认 C:\boost_1_88_0\stage\lib 包含所有依赖库。
-
确保使用 /MTd 运行时库,与 Boost 库一致。
-
-
连接失败:
-
检查防火墙是否阻止端口 8888/8889:
bash
netsh advfirewall firewall add rule name="Asio Ports" dir=in action=allow protocol=TCP localport=8888 netsh advfirewall firewall add rule name="Asio Ports UDP" dir=in action=allow protocol=UDP localport=8889
-
-
日志未生成:
-
确保当前目录有写权限。
-
检查 Boost.Log 配置是否正确。
-
5.2 优化建议
-
异步改进:
-
TCP 客户端可改为异步读写:
cpp
void async_read(tcp::socket& socket) { socket.async_read_some(asio::buffer(buffer_), [&socket](const boost::system::error_code& error, size_t len) { if (!error) { std::string response(buffer_.data(), len); BOOST_LOG_TRIVIAL(info) << "Received: " << response; async_read(socket); } }); }
-
-
多线程支持:
-
为服务器添加多线程:
cpp
std::vector<std::thread> threads; for (int i = 0; i < std::thread::hardware_concurrency(); ++i) { threads.emplace_back([&io_context] { io_context.run(); }); } io_context.run(); for (auto& t : threads) { if (t.joinable()) t.join(); }
-
-
超时处理:
-
添加定时器检测客户端超时:
cpp
asio::steady_timer timer_(io_context, std::chrono::seconds(30)); timer_.async_wait([](const boost::system::error_code& error) { if (!error) { BOOST_LOG_TRIVIAL(warning) << "Client timeout"; } });
-
6. 若 Boost 库仍未编译成功的解决方法
您提到仍在 x86 编译器环境,且多次尝试未生成 libboost_system-vc143-mt-gd-x64-1_88.lib 和 libboost_log-vc143-mt-gd-x64-1_88.lib。以下是针对性排查步骤:
-
确认 x64 环境:
-
运行:
bash
"C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" cl-
确保输出为 for x64。若仍为 x86,检查 Visual Studio 安装:
bash
start "" "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe"-
确保“C++ 桌面开发”包含 x64 工具。
-
-
-
-
重新编译 Boost:
-
清理:
bash
cd C:\boost_1_88_0 rmdir /S /Q stage rmdir /S /Q bin.v2 -
运行:
bash
bootstrap.bat .\b2.exe --toolset=msvc-14.3 address-model=64 architecture=x86 link=static threading=multi runtime-link=static variant=debug --with-system --with-log --with-thread --with-date_time --with-filesystem --with-regex stage > build_log.log 2>&1 -
检查 C:\boost_1_88_0\stage\lib。
-
-
检查日志:
-
打开 build_log.log,搜索 error 或 failed。
-
常见问题:
-
C1083:头文件缺失,重新下载 Boost 1.88.0。
-
LINK error:缺少依赖,确认 --with-regex。
-
x86 环境:重新运行 vcvars64.bat。
-
-
-
使用 vcpkg 快速获取库(备选):
-
安装 vcpkg:
bash
git clone https://github.com/microsoft/vcpkg cd vcpkg .\bootstrap-vcpkg.bat -
安装 Boost:
bash
.\vcpkg install boost-system:x64-windows-static boost-log:x64-windows-static -
集成到 Visual Studio:
bash
.\vcpkg integrate install
-
7. 总结
本教程介绍了 Boost.Asio 的网络编程基础,提供了 TCP 和 UDP 服务器与客户端的完整实现,结合 Boost.Log 记录通信日志,适合开发调试工具。代码使用 64 位调试版静态库,匹配您的需求。
后续教程预告:
-
教程(三):Boost.Log 高级日志配置(异步日志、过滤器、格式化)。
-
教程(四):Boost.Asio 进阶(SSL、协程、多线程、Boost.Beast)。
请提供以下信息以解决编译问题:
-
运行 cl 的最新输出(确认 x64)。
-
build_log.log 的关键错误。
-
C:\boost_1_88_0\stage\lib 的文件列表。
-
Visual Studio 版本和安装路径。
祝您 Boost.Asio 开发顺利!
更多推荐


所有评论(0)