Boost.Asio 同步读写及客户端 - 服务器实现详解
Boost.Asio 同步读写及客户端 - 服务器实现详解
参考文献
- Boost.Asio 官方文档
- 学习资料来源: 参考网址
一、引言
Boost.Asio作为一个强大的跨平台网络编程库,为开发者提供了丰富的网络操作接口。在之前的学习中,我们已接触到其同步读写的API函数,本文将在此基础上,深入探讨如何运用这些API构建一个完整且能实际运行的客户端与服务器示例,且双方均采用阻塞式的同步读写方式来实现通信。
二、客户端设计
- 设计思路:
- 首要任务是依据服务器的IP地址与端口号构建一个
endpoint,这是后续连接的目标定位信息。 - 借助
socket对象,向已确定的endpoint发起连接请求,尝试与服务器建立通信链路。 - 成功连接后,运用同步读写机制,实现向服务器发送数据以及接收服务器响应数据的功能。
- 首要任务是依据服务器的IP地址与端口号构建一个
- 代码剖析:
#include <iostream>
#include <boost/asio.hpp>
using namespace std;
using namespace boost::asio::ip;
const int MAX_LENGTH = 1024;int main() {try {// 1. 初始化Boost.Asio的核心对象io_context,它为后续的网络操作提供运行环境boost::asio::io_context ioc;// 2. 构建远程服务器的endpoint,明确通信目标的IP与端口,这里以本地回环地址127.0.0.1及端口10086为例tcp::endpoint remote_ep(address::from_string("127.0.0.1"), 10086);// 3. 创建用于网络通信的socket对象,绑定到之前创建的io_contexttcp::socket sock(ioc);// 4. 向服务器发起连接请求,并通过error_code检查连接结果boost::system::error_code error = boost::asio::error::host_not_found;sock.connect(remote_ep, error);// 若连接失败,输出错误详情并终止程序if (error) {cout << "连接失败,错误代码: " << error.value() << " 错误信息: " << error.message() << endl;return 0;}// 5. 提示用户输入要发送给服务器的消息std::cout << "请输入消息: ";char request[MAX_LENGTH];std::cin.getline(request, MAX_LENGTH);// 6. 计算输入消息的长度,并通过Boost.Asio的write函数将消息发送至服务器size_t request_length = strlen(request);boost::asio::write(sock, boost::asio::buffer(request, request_length));// 7. 准备接收服务器的回复,利用read函数从socket读取数据至reply缓冲区char reply[MAX_LENGTH];size_t reply_length = boost::asio::read(sock,boost::asio::buffer(reply, request_length));// 8. 输出服务器的回复内容std::cout << "服务器回复: ";std::cout.write(reply, reply_length);std::cout << "\n";}catch (std::exception& e) {// 捕获并处理任何可能出现的异常,输出错误信息std::cerr << "发生异常: " << e.what() << endl;}return 0;
}
三、服务器设计
服务器端的设计相对复杂,主要由两个关键函数协同完成工作。
session函数:- 功能定位:此函数专门负责处理单个客户端的连接请求。每当服务器监听到有新客户端接入时,便会立即调用该函数,对客户端的数据交互进行管理。
- 实现逻辑:采用循环结构,持续监听客户端发送的数据。一旦接收到数据,首先检查错误状态,若客户端正常关闭连接,函数能及时察觉并结束循环;若出现其他错误,则抛出异常。对于接收到的有效数据,不仅会在服务器端打印出来源客户端的IP地址以及消息内容,还会将数据原封不动地回传给客户端,实现简单的“echo”功能。
- 代码详情:
void session(std::shared_ptr<tcp::socket> sock) {try {for (;;) {char data[MAX_LENGTH];memset(data, '\0', MAX_LENGTH); // 初始化缓冲区,确保数据干净// 从客户端socket读取数据,同时关注可能出现的错误boost::system::error_code error;size_t length = sock->read_some(boost::asio::buffer(data, MAX_LENGTH), error);// 根据不同的错误情况进行相应处理if (error == boost::asio::error::eof) {std::cout << "连接被客户端关闭" << endl;break;} else if (error) {throw boost::system::system_error(error);}// 打印客户端连接信息及发送的消息std::cout << "收到来自 " << sock->remote_endpoint().address().to_string() << " 的消息" << endl;std::cout << "消息内容: " << data << endl;// 将接收到的消息原样回传给客户端boost::asio::write(*sock, boost::asio::buffer(data, length));}}catch (std::exception& e) {// 捕获并处理线程内出现的异常,输出错误详情std::cerr << "线程中发生异常: " << e.what() << "\n" << std::endl;}
}
server函数:- 功能定位:作为服务器的启动与管理核心,负责创建服务器的监听机制,并协调客户端连接的处理流程。
- 实现逻辑:首先创建一个
acceptor对象,绑定到指定的IP地址与端口,开始监听客户端的连接请求。进入无限循环后,每当有新客户端连接到来,便创建一个新的socket对象用于与该客户端通信,并立即启动一个独立的线程,在线程中调用session函数处理与该客户端的交互,同时将线程分离,使其能够独立运行,避免主线程阻塞。 - 代码详情:
void server(boost::asio::io_context& io_context, unsigned short port) {// 创建acceptor,用于监听指定端口的客户端连接tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), port));for (;;) {// 为新连接创建socket对象std::shared_ptr<tcp::socket> socket(new tcp::socket(io_context));acceptor.accept(*socket); // 接受客户端连接// 为每个连接创建独立线程处理通信,分离线程以独立运行auto t = std::make_shared<std::thread>(session, socket);t->detach(); }
}
- 多线程处理优势:通过为每个客户端连接分配独立的线程,并在其中进行读写操作,确保了服务器的
acceptor能够持续监听新连接,不会因某个连接的阻塞读写操作而陷入停滞,有效提升了服务器的并发处理能力。
四、同步读写的特性剖析
- 优点:
- 编程简易性:同步读写模式下,代码逻辑呈现顺序执行的特点,开发者无需处理复杂的异步回调嵌套,编写过程清晰明了,对于初学者或是处理简单网络场景的项目而言,上手难度较低,易于快速实现功能。
- 维护便利性:由于代码按照线性顺序执行,没有异步操作带来的回调函数分散在各处的问题,程序的逻辑流易于追踪与理解,后续的代码维护与调试工作相对轻松。
- 缺点:
- 阻塞隐患:在服务器端,若客户端未能及时发送数据,
read操作将会使线程陷入阻塞状态,白白消耗系统资源,直到有数据可读为止,这在高并发场景下极易引发性能瓶颈。 - 线程资源受限:鉴于每个连接都需要独立的线程来维持同步读写操作,而操作系统对线程数量存在上限限制(例如Linux系统默认2048个线程),当连接数大量增加时,系统可能无法创建足够的线程,导致新连接无法及时处理。
- 线程切换成本:大量线程的频繁切换会消耗大量的CPU时间用于上下文保存与恢复,使得系统用于实际业务处理的资源被削减,整体性能受到负面影响。
- 粘包问题未解决:无论是客户端还是服务器端,当前的同步读写实现都没有考虑到TCP协议在数据传输过程中可能出现的粘包现象,这可能导致接收端无法准确识别消息边界,造成数据解析错误。
- 阻塞隐患:在服务器端,若客户端未能及时发送数据,
五、改进方向展望
为克服同步读写的固有缺陷,引入异步读写模式成为必然选择:
- 并发性能飞跃:异步操作允许在等待数据读写完成的过程中,CPU能够转而处理其他任务,避免线程阻塞,从而能够在相同硬件资源下承载更多的客户端连接,大幅提升服务器的并发处理能力。
- 全双工通信优势:发送与接收数据的过程相互独立,不再受限于同步模式下的先后顺序,能够更好地适应复杂多变的通信需求,例如实时双向数据交互的场景。
- 粘包处理机制完善:可以通过在数据传输中添加特定的消息分隔符,或者在数据头部嵌入长度标识符等方式,让接收端能够精准地识别每条消息的边界,确保数据的完整性与准确性,提升系统的可靠性。
相关文章:
Boost.Asio 同步读写及客户端 - 服务器实现详解
Boost.Asio 同步读写及客户端 - 服务器实现详解 参考文献 Boost.Asio 官方文档学习资料来源: 参考网址 一、引言 Boost.Asio作为一个强大的跨平台网络编程库,为开发者提供了丰富的网络操作接口。在之前的学习中,我们已接触到其同步读写的API函数&…...
LeetCode 3019.按键变更的次数:遍历(转小写)
【LetMeFly】3019.按键变更的次数:遍历(转小写) 力扣题目链接:https://leetcode.cn/problems/number-of-changing-keys/ 给你一个下标从 0 开始的字符串 s ,该字符串由用户输入。按键变更的定义是:使用与…...
ETCD未授权测试
一、测试环境搭建 首先拉取etcd镜像 docker pull quay.io/coreos/etcd:v3.3.1 # 查看镜像 docker images创建自定义网络 docker network create --driver bridge --subnet172.16.1.0/16 --gateway172.16.1.1 mynet # 查看网络 docker network ls创建etcd节点 节点1: docke…...
【Hystrix-1】Hystrix:构建弹性分布式系统的基石
在分布式系统的广袤星图中,服务间的调用如同星辰间的引力,维系着系统的运转。然而,这种依赖关系也如同达摩克利斯之剑,一旦某个服务出现故障,便可能引发连锁反应,导致整个系统的崩塌。Hystrix,如…...
【超详细】MIT 液态神经网络(LNNs)——深度学习新动向
✅作者简介:双一流博士,人工智能领域学习者,深耕机器学习,交叉学科实践者。已发表SCI1/区top论文10+,授权专利4件,公开10+。可提供专利思路和指导,提供科研小工具,分享科研经验,欢迎交流! 📌个人主页: https://blog.csdn.net/allein_STR?spm=1011.2559.3001.5343…...
Git最便捷的迁移方式
#当公司要求git需要迁移时,你是不是感觉到束手无策。今天带来给大家最快,最便捷的迁移方式 这个命令是用于重命名git仓库中的远程仓库名。在这个命令中,我们将远程仓库的名字从"origin"改为"old-origin"。 git remote …...
2024AAAI SCTNet论文阅读笔记
文章目录 SCTNet: Single-Branch CNN with Transformer Semantic Information for Real-Time Segmentation摘要背景创新点方法Conv-Former Block卷积注意力机制前馈网络FFN 语义信息对齐模块主干特征对齐共享解码头对齐 总体架构backbone解码器头 对齐损失 实验SOTA效果对比Cit…...
Laravel操作ElasticSearch
在Laravel项目中操作ElasticSearch可以通过以下步骤来实现,通常会借助相应的ElasticSearch客户端扩展包。 ### 安装ElasticSearch客户端包 在Laravel项目中,常用的是 elasticsearch/elasticsearch 这个PHP客户端库来与ElasticSearch进行交互,…...
江科大STM32入门——SPI通信笔记总结
wx:嵌入式工程师成长日记 (一)简介 四根通信线:SCK、MOSI、MISO、SS(片选信号) 同步(同步通信是一种通信模式,在这种模式下,发送方和接收方在同一时刻进行数据传输。),全…...
微信小程序map组件所有markers展示在视野范围内
注意:使用include-points属性不生效,要通过createMapContext实现 <template><view class"map-box"><map id"map" class"map" :markers"markers" :enable-traffic"true" :enable-poi&…...
深度解析 tanh tanh 激活函数
1. 引言 在现代深度学习中,激活函数(Activation Function)是神经网络的核心组件之一。它的主要作用是引入非线性,从而使神经网络能够学习和表示复杂的非线性关系。如果没有激活函数,神经网络的输出将只是输入的线性组…...
嵌入式入门Day38
C Day1 第一个C程序C中的输入输出输出操作coutcin练习 命名空间使用方法自定义命名空间冲突问题 C对字符串的扩充C风格字符串的使用定义以及初始化C风格字符串与C风格字符串的转换C风格的字符串的关系运算常用的成员变量输入方法 布尔类型C对堆区空间使用的扩充作业 第一个C程序…...
探索Rancher服务发现机制:容器世界的“导航仪”
《探索Rancher服务发现机制:容器世界的“导航仪”》 在当今容器化技术蓬勃发展的时代,容器的大规模部署和微服务架构的广泛应用使得服务之间的相互发现与通信变得至关重要。Rancher作为一款功能强大的容器管理平台,其服务发现机制宛如一座无…...
【ROS2】Qt事件循环和ROS2订阅机制一起使用有什么注意事项?
1、简述 Qt的事件循环和ROS订阅回调函数都可能在阻塞函数中运行, 例如:Qt的QApplication::exec() 和 ROS的rclcpp::spin() 两个阻塞函数不能在同一个线程中使用,如果使用不当,会造成Qt不处理事件或者ROS2不处理订阅的回调函数。 2、多线程 一般 QApplication::exec() 运…...
donet (MVC)webAPI 的接受json 的操作
直接用对象来进行接收,这个方法还不错的。 public class BangdingWeiguiJiluController : ApiController{/// <summary>/// Json数据录入错误信息/// </summary>/// <param name"WeiguiInfos"></param>/// <returns></r…...
Qt 界面外观
一、前言 1、 一个完善的应用程序,不仅应该有实用的功能,还要有一个漂亮的外观,这样才能使应用程序更加友好,更加吸引用户。 2、 作为一个跨平台的UI开发框架,Qt提供了强大而灵活的界面外观设计机制。 3、 本篇会讲解&…...
aws(学习笔记第二十二课) 复杂的lambda应用程序(python zip打包)
aws(学习笔记第二十二课) 开发复杂的lambda应用程序(python的zip包) 学习内容: 练习使用CloudShell开发复杂lambda应用程序(python) 1. 练习使用CloudShell CloudShell使用背景 复杂的python的lambda程序会有许多依赖的包,如果不提前准备好这些python的…...
HTML课堂之搜索工具箱/讲师duluo
目录: 源码在最后 小提示: 1.养成打卡习惯没日多加练习即可提什能力 2.源码在最后,请先看完代码讲解,在尝试自己写,这样容易掌握 3.请勿复制粘贴,因为你没掌握,即使复制粘贴也学不会 课堂重点笔…...
当歌 - RSS 订阅分发平台开发
以下将详细介绍当歌平台的技术架构、功能实现以及相关代码逻辑。 一、项目概述 当歌是一个极简的 RSS 订阅分发平台,旨在为用户提供便捷的 RSS 管理和订阅服务,帮助用户轻松获取和分享最新资讯。 二、技术架构 后端语言:PHP 数据库&#…...
学习threejs,导入wrl格式的模型
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.VRMLLoader wrl模型加…...
日志系统建设:从“查问题”到“预测问题”
日志系统在软件测试中的核心地位 日志系统是软件测试从业者的“眼睛”,它记录了应用程序运行时的每一个关键事件,从用户操作到系统异常。传统上,日志主要用于事后故障排查(reactive approach),帮助测试人员…...
3步颠覆《流放之路》角色构建:从数据混乱到精准规划的实战革命
3步颠覆《流放之路》角色构建:从数据混乱到精准规划的实战革命 【免费下载链接】PoeCharm Path of Building Chinese version 项目地址: https://gitcode.com/gh_mirrors/po/PoeCharm 当你在《流放之路》中第5次洗练装备属性却仍未达到预期效果,当…...
如何打造终极纯净阅读体验:ReadCat免费开源小说阅读器完整指南
如何打造终极纯净阅读体验:ReadCat免费开源小说阅读器完整指南 【免费下载链接】read-cat 一款免费、开源、简洁、纯净、无广告的小说阅读器 项目地址: https://gitcode.com/gh_mirrors/re/read-cat 在数字阅读应用泛滥的今天,ReadCat免费开源小说…...
Simulink仿真避坑指南:如何设置步长、powergui和模块采样时间才能让控制周期更稳定
Simulink控制系统仿真参数配置实战:从步长到采样时间的精准调优 在电机控制、电力电子系统等工业仿真场景中,Simulink参数的合理配置直接决定了仿真结果的可靠性与工程指导价值。许多工程师第一次搭建控制系统模型时,往往被各种时间参数搞得晕…...
别再数据线了!用FastAPI 分钟搭个局域网文件+剪贴板神器伊
为 HagiCode 添加 GitHub Pages 自动部署支持 本项目早期代号为 PCode,现已正式更名为 HagiCode。本文记录了如何为项目引入自动化静态站点部署能力,让内容发布像喝水一样简单。 背景/引言 在 HagiCode 的开发过程中,我们遇到了一个很现实的问…...
如何用GHelper替代Armoury Crate:华硕笔记本轻量级控制工具完整指南
如何用GHelper替代Armoury Crate:华硕笔记本轻量级控制工具完整指南 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, T…...
开源六轴机械臂:3D打印谐波减速器技术如何打破工业自动化成本壁垒
开源六轴机械臂:3D打印谐波减速器技术如何打破工业自动化成本壁垒 【免费下载链接】Faze4-Robotic-arm All files for 6 axis robot arm with cycloidal gearboxes . 项目地址: https://gitcode.com/gh_mirrors/fa/Faze4-Robotic-arm 工业自动化的普及面临着…...
突破网盘下载限制:本地安全处理的直链解析方案
突破网盘下载限制:本地安全处理的直链解析方案 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 ,支持 百度网盘 / 阿里云盘 / 中国移动云盘 / 天翼云盘 / …...
如何快速掌握OpenEMS:开源能源管理系统的完整指南
如何快速掌握OpenEMS:开源能源管理系统的完整指南 【免费下载链接】openems OpenEMS - Open Source Energy Management System 项目地址: https://gitcode.com/gh_mirrors/op/openems 想要打造智能能源管理系统却不知从何入手?OpenEMS开源能源管理…...
一键部署清音听真:Qwen3-ASR-1.7B高精度语音识别系统开箱即用
一键部署清音听真:Qwen3-ASR-1.7B高精度语音识别系统开箱即用 1. 语音识别技术的新突破 在数字化办公日益普及的今天,语音识别技术已成为提升工作效率的重要工具。然而,传统语音识别系统在面对复杂场景时往往捉襟见肘——背景噪音、专业术语…...
