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

【Linux篇】应用层自定义协议与序列化

📌个人主页:孙同学_
🔧文章专栏:Liunx
💡关注我,分享经验,助你少走弯路!

应用层

我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应用层。

再谈 “协议”
协议是一种 “约定”socket api的接口, 在读写数据时, 都是按 “字符串” 的方式来发送接收的. 如果我们要传输一些 “结构化的数据” 怎么办呢?

其实,协议就是双方约定好的结构化的数据

网络版计算器
例如,我们需要实现一个服务器版的加法器.我们需要客户端把要计算的两个加数发过去,然后由服务器进行计算,最后再把结果返回给客户端.

约定方案一:

客户端发送一个形如"1+1"的字符串;
这个字符串中有两个操作数,都是整形;
两个数字之间会有一个字符是运算符,运算符只能是+;
数字和运算符之间没有空格;

约定方案二:

定义结构体来表示我们需要交互的信息;
发送数据时将这个结构体按照一个规则转换成字符串,接收到数据的时候再按照相同的规则把字符串转化回结构体;
这个过程叫做"序列化"和"反序列化"


我们把结构化的数据拆成字符串叫做序列化,我们把一行字符串按照特定的格式拆分变成一个结构化对象叫做反序列化。

序列化的作用:保证报文的完整性,方便报文传送。
反序列化:方便上层进行处理。

我们把两种结构体叫做客户端与服务端约定好的协议。


结论:如果我们我们要进行网络通信,在应用层,强烈建议使用序列化和反序列化方案。至于直接穿结构体的方案,除非场景特殊,否则不建议。

重新理解 read、write、recv、send 和 tcp 为什么支持全双工



因为TCP是面向字节流的,在我们的单词翻译模块,在读的时候,有可能读到一个单词,也有可能读到半个单词。我们的buffer中有可能不是一个完整的单词,所以在TCP这里我们就要对它处理。在UDP中并不存在这样的问题,在UDP中要么不读报文,要读就读一个完整的报文。

未来我们的协议:

  1. 结构化字段,提供序列化和反序列化方案
  2. 解决因为字节流问题,导致读取报文不完整的问题(只处理读取)

网络版计算器

socket封装 – 模板方法模式

自定义协议

设计服务器

守护进程化


jsoncpp

Jsoncpp是一个用于处理JSON数据的C++库。它提供了将JSON数据序列化为字符串以及从字符串反序列化为C++数据结构的功能。Jsoncpp是开源的,广泛用于各种需要处理JSON数据的C++项目中。
特性

  1. 简单易用:Jsoncpp提供了直观的API,使得处理JSON数据变得简单。
  2. 高性能:Jsoncpp的性能经过优化,能够高效地处理大量JSON数据。
  3. 全面支持:支持JSON标准中的所有数据类型,包括对象、数组、字符串、数字、布尔值和null。
  4. 错误处理:在解析JSON数据时,Jsoncpp提供了详细的错误信息和位置,方便开发者调试。

当使用Jsoncpp库进行JSON的序列化和反序列化时,确实存在不同的做法和工具类可供选择。以下是对Jsoncpp中序列化和反序列化操作的详细介绍:

安装

ubuntu:sudo apt-get install libjsoncpp-dev Centos:sudo yum install jsoncpp-devel

怎么判断我们的系统里有没有把别人的库装好呢?
1.我们使用别人的开源库,我们在下载安装的时候安装的是别人的库,当我们在使用库时是需要头文件的。
所以我们在安装的时候就需要安装库的头文件和.so文件

如果我们此时出现了jsoncpp的目录并且里面包含了json,并且json里面包含了下面内容。

就证明我们的json库就已经安装成功了。

序列化
序列化是指将数据结构或对象转化为一种格式,以便到网络中传输或者保存在文件中。Jsoncpp提供了多种方式进行序列化。

  1. 使用 Json::Value 的 toStyledString 方法
  • 优点:将 Json::Value 对象直接转换为格式化的 JSON 字符串。
  • 示例:
#include<iostream>#include<string>#include<jsoncpp/json/json.h>intmain(){Json::Value root;root["name"]="张三";root["sex"]="男";root["age"]=18;std::string s=root.toStyledString();std::cout<<s<<std::endl;return0;}

小细节:
当我们在用json头文件的时候,我们需要:

#include<jsoncpp/json/json.h>

原因是我们的系统只能查找到include,我们使用的<stdio.h>在include下面,而我们今天所需要的头文件json.h需要把前导路径带上。

/
2.使用 Json::StreamWriter:

  • 优点:提供了更多的定制选项,如缩进、换行符等。
  • 示例:
#include<iostream>#include<string>#include<sstream>#include<memory>#include<jsoncpp/json/json.h>intmain(){Json::Value root;root["name"]="joe";root["sex"]="男";Json::StreamWriterBuilder wbuilder;// StreamWriter 的工厂 std::unique_ptr<Json::StreamWriter>writer(wbuilder.newStreamWriter());std::stringstream ss;writer->write(root,&ss);std::cout<<ss.str()<<std::endl;return0;}$./test.exe{"name":"joe","sex":"男"}
  1. 使用 Json::FastWriter:
  • 优点:比 StyledWriter 更快,因为它不添加额外的空格和换行符。
  • 示例:
#include<iostream>#include<string>#include<jsoncpp/json/json.h>intmain(){Json::Value root;root["name"]="张三";root["sex"]="男";root["age"]=18;Json::FastWriter writer;//去掉换行,网络传送的数据量不久小了,所以效率高std::string s=writer.write(root);std::cout<<s<<std::endl;return0;}

#include<iostream>#include<string>#include<jsoncpp/json/json.h>intmain(){Json::Value root;root["name"]="张三";root["sex"]="男";root["age"]=18;Json::StyledWriter writer;//用\n给我们进行按行设置了,可读性比较好std::string s=writer.write(root);std::cout<<s<<std::endl;return0;}

反序列化
反序列化是将序列化的数据重新转化为原来的数据结构或者对象。jsoncpp提供了一下进行反序列化的方法:

  1. 使用Json::Reader
  • 优点:提供详细的错误信息和错误位置,方便调试
  • 示例:
  1. 使用Json::CharReader的派生类(不推荐)
  • 在某些情况下,你可能需要更精细地控制解析过程,可以直接使用Json::CharReader的派生类。
  • 但通常情况下,使用Json::parseFromStreamJson::Reader的parse方法就足够了。


有没有一种可能就是我们的发送端只发送了一部分报文给接收端,而不是一条完整的报文呢?在读取的时候不就只读到了json字符串的一部分了吗?还有一种情况是我们接收了三个请求,但是当我们读取的时候,我们只读到了一个请求和下一个请求的一半。

问题:因为tcp是面向字节流的。
当读取方在读取的时候,可能读到一个完整的请求,也可能读到半个,一个半,五个半,全都有可能发生,所以read并不能保证读取报文的完整性!!!它只保证如果数据有,就读上来,并不能保证报文的完整性,这叫做tcp的面向字节流

谁来保证呢?答案是由上层应用层程序员自己来保证

我们规定,客户端发过来的请求还要包含一个字段:有效载荷的长度,这个长度表示json串的长度,为了增加区分度,我们在有效长度和Json串之间加个/r/n来区别,在Json串的结尾加上/r/n


总结:所有在命令行启动的都叫做作业,作业可以由一个进程组构成,也可以由多个进程组构成。作业也分为前台作业和后台作业,前台作业只能由一个,后台作业可以有多个

守护进程 vs前台进程 vs 后台进程

前台进程和后台进程属于同一个会话,前台和后台相比,拥有标准输入的是前台进程,后台进程不拥有标准输入的使用权。守护进程也是后台进程的一种,但是它是拥有独立会话的。

如何把自己变成一个独立的会话,成为独立会话内部的作业呢?
做法很简单,只需要调用setsid

一个进程如果调用这个setsid就会创建一个新的会话,前提:调用setsid的进程不能是一个进程组的组长。
守护进程也是孤儿进程的一种。


👍如果对你有帮助,欢迎:

  • 点赞 ⭐️
  • 收藏 📌
  • 关注 🔔
http://www.jsqmd.com/news/607656/

相关文章:

  • 艾尔登法环帧率解锁与游戏增强工具:完整使用指南
  • 2025-2026年全球财富管理公司评测:五家口碑服务推荐评价领先 - 品牌推荐
  • Pi0具身智能v1效果对比:STM32CubeMX硬件控制性能测试
  • Android加固公司怎么选?2026年移动应用安全服务商综合决策指南
  • 绕过Docker版Home Assistant的Supervisor限制:在华为盒子海纳思系统上手动安装HACS的完整指南
  • Stable Diffusion三大核心组件实战解析:从VAE压缩到CLIP文本控制的完整流程
  • 从技术参数到售后保养:废水处理设备推荐生产厂家及型号全攻略 - 品牌推荐大师
  • CSS3 字体深度解析
  • 告别Side-by-Side配置难题:VisualCppRedist AIO让运行库管理更简单
  • andrej-karpathy-skills配置迁移指南:从旧版本到新版本
  • 开源可审计翻译方案:translategemma-27b-it保障数据隐私与合规性
  • 百度网盘Mac版速度优化:从受限下载到高速体验的完整解决方案
  • 2025-2026年全球财富管理公司推荐:五大口碑产品评测对比顶尖 - 品牌推荐
  • 2025-2026年全球财富管理公司评测:五家口碑产品推荐对比顶尖 - 品牌推荐
  • Crystal架构深度解析:Electron桌面应用如何管理多个AI实例
  • 10个最常见的后端面试问题及最佳回答策略 | Back-End-Developer-Interview-Questions
  • 百联OK卡闲置别扔,可可收94.5折回收,几分钟到账 - 可可收
  • Maya2027|Win中文|三维建模动画软件|安装教程
  • 多模态学习(五):基于可变形注意力的无人机可见光-红外图像配准:Transformer架构优化与实践
  • 网络设备调试好帮手:手把手教你用3CDaemon搭建TFTP服务器备份交换机配置
  • 2026寻找正规管道安装公司?宏创巨建设资质齐全服务更放心 - 品牌2026
  • 5大维度重构输入体验:QKeyMapper全设备协同与输入重定义技术解析
  • 2026厂房无尘室工程找谁做?推荐专业承包商宏创巨建设 - 品牌2026
  • Qt5 cmake中如何正确引用第三方库的private头文件
  • 2026 年 AI 知识与 BI 部署标杆厂商:企业知识库部署、AI 知识库方案、Deepseek 知识库服务、智能 BI 私有化部署、BI 本地部署厂商推荐 - 品牌2026
  • MySQL 实战进阶:从单表优化到分布式数据库适配
  • React-sticky高级用法:相对容器、偏移量与硬件加速优化
  • 上饶儿童摄影哪家靠谱,对认生宝宝拍照有办法且修图自然? - mypinpai
  • 2026年折盖封箱机制造厂价格分析,看看哪家性价比高 - 工业品牌热点
  • 释放磁盘空间:SteamCleaner全方位清理方案