当前位置: 首页 > article >正文

手把手用C++实现一个基于Protobuf的简易聊天程序(附完整源码)

从零构建基于Protobuf的C聊天程序完整实现与深度解析在分布式系统开发中高效的数据序列化与网络通信是核心挑战。本文将带您完整实现一个基于Protobuf的聊天程序涵盖协议设计、网络通信模型到实际部署的全流程。不同于简单的代码示例我们将深入探讨工程实践中的关键设计决策和性能优化技巧。1. 环境准备与项目架构1.1 开发环境配置首先确保系统已安装以下组件Protobuf 3.19 编译器CMake 3.12C17兼容的编译器GCC 9/Clang 10安装Protobuf开发库Ubuntu示例sudo apt install libprotobuf-dev protobuf-compiler验证安装protoc --version # 应显示3.x版本1.2 项目目录结构采用模块化设计建议按以下结构组织代码chat-system/ ├── CMakeLists.txt ├── include/ │ ├── chat.pb.h │ └── network_utils.h ├── proto/ │ └── chat.proto ├── src/ │ ├── client.cpp │ ├── server.cpp │ └── network_utils.cpp └── build/2. Protobuf协议设计2.1 消息类型定义在proto/chat.proto中定义核心协议syntax proto3; package chat; message User { string id 1; string name 2; uint32 avatar_id 3; } message TextMessage { string content 1; uint64 timestamp 2; User sender 3; } message FileAttachment { string file_name 1; bytes content 2; string mime_type 3; } message ChatMessage { oneof content { TextMessage text 1; FileAttachment file 2; } repeated string recipients 3; }关键设计要点使用oneof实现消息多态时间戳采用uint64存储Unix时间二进制文件直接以bytes类型传输2.2 协议编译与代码生成使用以下命令生成C代码protoc --proto_pathproto --cpp_outinclude proto/chat.proto这将生成chat.pb.h消息类声明chat.pb.cc实现代码提示在CMake中可添加自定义命令自动执行此步骤3. 网络通信实现3.1 TCP通信基础框架在network_utils.h中定义网络接口#include sys/socket.h #include netinet/in.h class NetworkManager { public: bool SendProtobuf(int sockfd, const google::protobuf::Message msg); bool RecvProtobuf(int sockfd, google::protobuf::Message* msg); private: const static uint32_t MAX_MSG_SIZE 10 * 1024 * 1024; // 10MB };实现消息收发核心逻辑bool NetworkManager::SendProtobuf(int sockfd, const google::protobuf::Message msg) { std::string serialized; if (!msg.SerializeToString(serialized)) { return false; } uint32_t size htonl(serialized.size()); if (send(sockfd, size, sizeof(size), 0) ! sizeof(size)) { return false; } return send(sockfd, serialized.data(), serialized.size(), 0) static_castssize_t(serialized.size()); }3.2 服务端实现服务器核心逻辑server.cpp节选void RunServer(uint16_t port) { int server_fd socket(AF_INET, SOCK_STREAM, 0); sockaddr_in addr { .sin_family AF_INET, .sin_port htons(port), .sin_addr { INADDR_ANY } }; bind(server_fd, (sockaddr*)addr, sizeof(addr)); listen(server_fd, 5); while (true) { int client_fd accept(server_fd, nullptr, nullptr); std::thread([client_fd] { chat::ChatMessage msg; while (NetworkManager::RecvProtobuf(client_fd, msg)) { ProcessMessage(msg); } close(client_fd); }).detach(); } }3.3 客户端实现客户端消息发送示例void SendTextMessage(int sockfd, const std::string text) { chat::ChatMessage msg; chat::TextMessage* text_msg msg.mutable_text(); text_msg-set_content(text); text_msg-set_timestamp(time(nullptr)); chat::User* user text_msg-mutable_sender(); user-set_id(user123); user-set_name(Alice); NetworkManager::SendProtobuf(sockfd, msg); }4. 高级功能实现4.1 消息持久化存储使用Protobuf实现消息日志class MessageLogger { public: bool Append(const chat::ChatMessage msg) { std::ofstream out(log_path_, std::ios::binary | std::ios::app); return msg.SerializeToOstream(out); } std::vectorchat::ChatMessage LoadHistory() { std::ifstream in(log_path_, std::ios::binary); std::vectorchat::ChatMessage history; chat::ChatMessage msg; while (msg.ParseFromIstream(in)) { history.push_back(msg); } return history; } };4.2 性能优化技巧复用Message对象thread_local chat::ChatMessage recv_msg; // 每个线程独立实例 while (NetworkManager::RecvProtobuf(fd, recv_msg)) { Process(recv_msg); recv_msg.Clear(); }预分配缓冲区msg.SerializeToString(serialized_buf_); // 复用同一缓冲区零拷贝优化message LargeFile { bytes chunk 1 [ctype CORD]; // 使用CORD类型减少拷贝 }5. 安全与错误处理5.1 输入验证框架bool ValidateMessage(const chat::ChatMessage msg) { if (msg.has_text()) { const auto text msg.text(); if (text.content().size() 1024) { return false; // 限制消息长度 } } else if (msg.has_file()) { const auto file msg.file(); if (file.content().size() 10 * 1024 * 1024) { return false; // 限制文件大小 } } return true; }5.2 异常处理模式网络层错误处理示例try { if (!msg.SerializeToString(buf)) { throw SerializationError(Failed to serialize message); } if (send(fd, buf.data(), buf.size(), 0) 0) { throw NetworkError(strerror(errno)); } } catch (const std::exception e) { std::cerr Error: e.what() std::endl; Reconnect(); }6. 构建与部署6.1 CMake集成配置完整CMake示例cmake_minimum_required(VERSION 3.12) project(ChatSystem) find_package(Protobuf REQUIRED) protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS proto/chat.proto) add_executable(server src/server.cpp src/network_utils.cpp ${PROTO_SRCS}) target_include_directories(server PRIVATE include) target_link_libraries(server PRIVATE protobuf pthread) add_executable(client src/client.cpp src/network_utils.cpp ${PROTO_SRCS}) target_include_directories(client PRIVATE include) target_link_libraries(client PRIVATE protobuf)6.2 容器化部署Dockerfile示例FROM ubuntu:20.04 RUN apt update apt install -y libprotobuf23 COPY build/server /app/ COPY build/client /app/ CMD [/app/server, 8080]构建命令docker build -t chat-server . docker run -p 8080:8080 chat-server7. 测试与性能基准7.1 单元测试框架使用Google Test测试序列化TEST(ProtocolTest, TextMessageSerialization) { chat::TextMessage msg; msg.set_content(Hello); msg.set_timestamp(123456789); std::string serialized; ASSERT_TRUE(msg.SerializeToString(serialized)); chat::TextMessage parsed; ASSERT_TRUE(parsed.ParseFromString(serialized)); EXPECT_EQ(msg.content(), parsed.content()); }7.2 性能对比数据测试环境Intel i7-1185G7, 16GB RAM操作Protobuf (μs)JSON (μs)序列化1KB文本1245反序列化1KB文本1862传输10MB文件15200423008. 扩展与进阶方向8.1 多语言支持方案通过gRPC实现跨语言通信service ChatService { rpc SendMessage (ChatMessage) returns (Ack); rpc StreamMessages (stream ChatMessage) returns (stream ChatMessage); }8.2 消息加密集成使用OpenSSL进行端到端加密void EncryptMessage(const chat::ChatMessage msg, EVP_PKEY* key) { std::string serialized; msg.SerializeToString(serialized); EVP_CIPHER_CTX* ctx EVP_CIPHER_CTX_new(); EVP_SealInit(ctx, EVP_aes_256_cbc(), enc_key, enc_key_len, iv, pub_key, 1); // ... 加密处理 ... }在实际项目中我们发现合理设置TCP_NODELAY选项可显著降低小消息的延迟。对于高频聊天场景建议将消息批量打包发送相比单条发送可提升30%以上的吞吐量。

相关文章:

手把手用C++实现一个基于Protobuf的简易聊天程序(附完整源码)

从零构建基于Protobuf的C聊天程序:完整实现与深度解析 在分布式系统开发中,高效的数据序列化与网络通信是核心挑战。本文将带您完整实现一个基于Protobuf的聊天程序,涵盖协议设计、网络通信模型到实际部署的全流程。不同于简单的代码示例&…...

LoRa_AT库:面向AT指令型LoRa模块的轻量Arduino驱动

1. LoRa_AT 库概述:面向 AT 指令型 LoRa 模块的轻量级 Arduino 驱动框架LoRa_AT 是一个专为基于 AT 指令通信的 LoRa 模块设计的轻量级 Arduino C 类库。其核心定位并非通用蜂窝通信(如 GSM/LTE),而是聚焦于一类广泛应用于低功耗广…...

Cadence原理图模块化避坑指南:从‘电气检查报错’到‘一键同步更新’的完整流程

Cadence原理图模块化避坑指南:从‘电气检查报错’到‘一键同步更新’的完整流程 在电子设计自动化(EDA)领域,Cadence作为行业标杆工具链,其原理图模块化功能能显著提升复杂电路设计的可维护性。但许多工程师在从单体设…...

LTC230x I²C高精度ADC驱动深度解析与嵌入式实践

1. LTC230x系列ADC库深度解析:面向嵌入式工程师的IC高精度模数转换实践指南Linear Technology(现为Analog Devices)LTC230x系列是工业级12位逐次逼近型(SAR)模数转换器,专为低功耗、高精度、多通道模拟信号…...

5G NR PBCH处理流程详解:从MIB到天线映射的完整指南

5G NR PBCH处理流程详解:从MIB到天线映射的完整指南 在5G通信系统中,物理广播信道(PBCH)承载着网络最基本的配置信息,是终端设备(UE)接入网络的第一道"钥匙"。作为同步信号块(SSB)的核心组成部分,PBCH的处理流程涉及多个…...

5分钟搞懂多项式不可约性:从复数域到有限域的实战指南

5分钟搞懂多项式不可约性:从复数域到有限域的实战指南 多项式不可约性是代数学中的核心概念,也是密码学、编码理论等领域的数学基础。本文将带你快速理解不同数域下的不可约多项式判定方法,并通过Python和SageMath代码示例展示实际操作技巧。…...

FRCRN语音降噪工具实战案例:会议室录音去空调/键盘/人声交叠噪声效果展示

FRCRN语音降噪工具实战案例:会议室录音去空调/键盘/人声交叠噪声效果展示 1. 项目背景与价值 在现代办公环境中,会议录音质量往往受到各种环境噪声的严重影响。空调的低频嗡嗡声、键盘敲击的咔嗒声、多人同时发言的语音交叠,这些噪声不仅影…...

老设备激活指南:使用OpenCore Legacy Patcher实现Mac系统兼容性突破

老设备激活指南:使用OpenCore Legacy Patcher实现Mac系统兼容性突破 【免费下载链接】OpenCore-Legacy-Patcher 体验与之前一样的macOS 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款专为Intel架…...

香橙派5 NPU性能实测:yolov5在RK3588上的推理速度到底有多快?

香橙派5 NPU实战:RK3588芯片如何实现yolov5百帧级实时推理 当我在工作室第一次用香橙派5运行yolov5模型时,监控画面中的人流检测框像被施了魔法般流畅滑动——这完全颠覆了我对单板计算机AI性能的认知。作为RK3588芯片的招牌特性,那颗6TOPS算…...

PHP7.4性能优化:在银河麒麟V10 SP2系统上开启OPcache的完整配置指南

PHP7.4性能优化:在银河麒麟V10 SP2系统上开启OPcache的完整配置指南 对于运行在银河麒麟V10 SP2系统上的PHP应用来说,性能优化是一个永恒的话题。作为国产操作系统的代表,银河麒麟V10 SP2在x86架构上表现出色,而PHP7.4则是目前许多…...

电赛硬件手记:实测TLV3501高速比较器,从芯片手册到100MHz方波生成(附PCB设计避坑点)

电赛实战:TLV3501高速比较器从设计到100MHz方波生成的完整指南 引言:为什么TLV3501是电赛选手的秘密武器? 去年省赛现场,我看到至少三支队伍因为比较器电路不稳定而痛失测量分——他们的方波边缘抖动得像心电图,频率计…...

FPGA工程师的日常:用Verilog和QuartusⅡ快速验证一个加法器IP核的设计思路

FPGA加法器IP核实战:从Verilog设计到QuartusⅡ高效验证 早上九点,咖啡的香气弥漫在工位周围。作为FPGA工程师,今天要完成一个看似简单却至关重要的任务——为图像处理流水线设计一个可复用的加法器IP核。这个基础模块将成为后续卷积运算加速的…...

CiteSpace关键词共现图实战指南:从数据清洗到可视化优化

最近在帮实验室的师弟处理文献数据,他抱怨说用 CiteSpace 做关键词共现图时,导出的 Web of Science 数据经常格式错乱,节点标签挤成一团根本看不清,调整参数又特别耗时。这让我想起自己以前也踩过同样的坑。其实,用 Py…...

RS485与Modbus通信协议:从硬件到软件的完整解析(含Modbus Poll/Slave实战)

RS485与Modbus通信协议:从硬件到软件的完整解析(含Modbus Poll/Slave实战) 工业自动化领域的数据通信就像人体的神经系统,而RS485与Modbus协议则是这个系统中至关重要的"神经纤维"与"语言规范"。想象一下&…...

告别数据抖动!树莓派DHT11温湿度监测的5个稳定性优化技巧

告别数据抖动!树莓派DHT11温湿度监测的5个稳定性优化技巧 在智能家居和物联网项目中,DHT11温湿度传感器因其低成本、易用性成为许多开发者的首选。但当项目从实验阶段转向实际应用时,数据抖动、偶发报错等问题常常困扰着开发者。本文将分享五…...

iic/ofa_image-caption_coco_distilled_en部署教程:Ubuntu 22.04 + CUDA 11.8环境适配方案

iic/ofa_image-caption_coco_distilled_en部署教程:Ubuntu 22.04 CUDA 11.8环境适配方案 1. 项目概述 OFA图像英文描述系统基于iic/ofa_image-caption_coco_distilled_en模型构建,能够对输入的图片自动生成准确的自然语言描述。这个系统特别适合需要为…...

Cadence Allegro精准更新PCB封装的实用技巧

1. 为什么需要精准更新PCB封装? 在PCB设计过程中,封装更新是再常见不过的操作了。你可能遇到过这样的情况:某个电阻的丝印被误删了一截,或者某个IC的焊盘尺寸需要微调,但同类型的其他元件却不需要改动。如果直接全局更…...

UGUI虚拟列表优化:实现高性能ListView组件

1. 为什么需要虚拟列表技术 在Unity游戏开发中,UGUI的ListView组件是展示大量数据的常用控件,比如排行榜、背包系统、聊天记录等场景。但原生ScrollRect有个致命问题:它会一次性创建所有子项。想象一下,如果你的排行榜有10000名玩…...

用Python处理百万级数据过滤?这3个性能陷阱90%人会踩

Python百万级数据过滤实战:避开这3个性能陷阱 当数据规模膨胀到百万级别时,Python脚本突然变得缓慢不堪——这是许多开发者都经历过的噩梦。上周我处理一个包含200万条用户行为记录的数据集时,原本只需几秒的过滤操作突然耗时超过5分钟。经过…...

OpenClaw技能组合技:Qwen3.5-9B完成竞品监控日报自动化

OpenClaw技能组合技:Qwen3.5-9B完成竞品监控日报自动化 1. 为什么需要自动化竞品监控 每天早上打开电脑的第一件事,就是手动检查十几个竞品网站的动态。这个习惯我坚持了两年多,直到上个月发现某竞品悄悄上线了新功能而我整整晚了一周才注意…...

IndexTTS2 V23在影视配音中的应用:快速验证你的创意想法

IndexTTS2 V23在影视配音中的应用:快速验证你的创意想法 1. 引言:影视配音的新工具 在影视创作过程中,配音环节往往需要耗费大量时间和人力成本。传统配音需要专业录音棚、配音演员和后期处理,这使得创意验证变得昂贵且耗时。In…...

DAMO-YOLO性能优化技巧:如何调整参数以获得更快的推理速度

DAMO-YOLO性能优化技巧:如何调整参数以获得更快的推理速度 1. 引言:为什么需要优化DAMO-YOLO的推理速度 在实际工业应用中,目标检测系统的推理速度直接影响着用户体验和系统吞吐量。DAMO-YOLO虽然已经具备出色的实时性能,但在某…...

nftables实战:用Set和Map轻松管理上千个IP黑名单(附自动封禁脚本)

nftables实战:用Set和Map轻松管理上千个IP黑名单(附自动封禁脚本) 在今天的网络环境中,网站管理员和安全工程师经常面临一个共同的挑战:如何高效地管理大量动态IP地址的黑名单。无论是应对CC攻击、恶意爬虫还是其他形式…...

VDEAI多光谱数据集YOLO格式转换实战:从原始标注到训练集构建

1. 理解VDEAI多光谱数据集与YOLO格式需求 第一次接触VDEAI数据集时,我被它独特的双模态特性吸引了。这个数据集包含可见光(RGB)和红外(IR)图像对,每对图像共享相同的场景但来自不同光谱波段。比如文件名&qu…...

工业C内存池扩容失败率骤降76%的实战方案(NASA航天器固件验证版)

第一章:工业C内存池扩容策略在高实时性、低延迟要求的工业嵌入式系统中,动态内存分配(如 malloc/free)因碎片化、不可预测的执行时间及锁竞争风险而被严格规避。工业C内存池通过预分配固定大小的内存块集合实现确定性内存管理&…...

Odoo 18企业版源码‘学习版’部署避坑指南:从下载到成功登录Web UI的全流程

Odoo 18企业版源码学习环境搭建全流程实战指南 引言 对于ERP系统开发者和企业信息化管理者来说,Odoo无疑是一个极具吸引力的开源解决方案。特别是其企业版提供的丰富功能模块,往往能大幅提升业务管理效率。然而,由于企业版授权限制&#xff0…...

Nanbeige 4.1-3B 创意写作效果PK:不同风格指令下的文本生成

Nanbeige 4.1-3B 创意写作效果PK:不同风格指令下的文本生成 想看看一个3B参数的小模型,到底能不能玩转创意写作?今天咱们就拿最近挺火的Nanbeige 4.1-3B来做个实验。我不打算讲那些复杂的部署和参数,就想看看最实在的东西&#x…...

2027 AI 人人都用的套餐是什么? 趋势展望与猜想

声明本篇内容仅为未来趋势展望与猜想,不构成投资与消费建议,仅供大家参考。核心预测2027 年,AI 服务将全面实现普惠化,大部分人都会主动接受并购买 AI 基础套餐。与此同时,运营商会将 AI 额度与手机套餐绑定&#xff0…...

SLAM硬件搭建避坑指南:RoboSense激光雷达+Wheeltec IMU+Autolabor底盘实战配置

SLAM硬件搭建避坑指南:RoboSense激光雷达Wheeltec IMUAutolabor底盘实战配置 当你第一次尝试搭建SLAM硬件系统时,面对琳琅满目的传感器和复杂的配置流程,很容易陷入各种"坑"中。本文将分享我在使用RoboSense 16线激光雷达、Wheelte…...

别再为PPT熬夜了!我用Gamma AI 5分钟搞定了一份惊艳的英文汇报

职场效率革命:用AI工具5分钟打造专业级英文汇报 凌晨两点的办公室,咖啡杯已经见底,而你的英文汇报PPT还停留在空白页面——这个场景对跨国企业员工、学术研究者或自由职业者来说都不陌生。传统PPT制作消耗的远不止是时间,更是创作…...