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

【计算机网络学习之路】序列化,反序列化和初识协议

文章目录

  • 前言
  • 一. 序列化和反序列化
    • 1.自己实现
    • 2. JSON
  • 二. 初识协议
  • 结束语

前言

本系列文章是计算机网络学习的笔记,欢迎大佬们阅读,纠错,分享相关知识。希望可以与你共同进步。

本篇博文正式开始应用层的学习,首先讲解应用层的序列化和反序列化,还有了解简单的应用层传输协议

一. 序列化和反序列化

在前篇TCP和UDP服务器编写时,业务只是简单的echo客户端发送的数据,但实际生活中,要传输的数据往往复杂的多。使用结构体或类可以保存更多数据,但传输过程中,可能会遇到网络通信两端的操作系统不同,结构体/类的大小不同,内存对齐策略不一致等问题。所以网络传输十分不建议传输结构体或类
这时,序列化和反序列化诞生了。

序列化通俗来说,就是将结构体/类转化为字符串;而反序列化就是将字符串转化为结构体

序列化最重要的作用:在传递和保存对象时,保证对象的完整性和可传递性等问题。对象转换为有序字节流,以便在网络上传输或者保存在本地文件中。

反序列化最重要的作用:根据字节流中保存的对象状态及描述信息,通过反序列化重建对象

核心作用就是对象状态的保存和重建。(整个过程核心点就是字节流所保存的对象状态及描述信息

1.自己实现

案例

假如我们现在要实现一个网络版本的计算器
我们把客户端发送的数据称为需求(Request),服务器返回的数据叫做响应(Responce)
此案例的需求有三个变量:数字x,数字y,操作数op
响应有两个变量:结果result,结果码code
需求和响应都需要有序列化反序列化两个功能函数
代码如下:

使用分割符方便Request提取变量,分隔符——空格
1+1 =>(添加分隔符) 1 + 1


#define SEP " " //分隔符
#define SEP_LEN strlen(SEP)
// 请求
class Request
{
public:Request() {}// 序列化 结构体=>字符串bool Serialize(std::string *outStr){*outStr = "";std::string x_string = std::to_string(_x);std::string y_string = std::to_string(_y);//添加分隔符*outStr = x_string + SEP + _op + SEP + y_string;return true;}// 反序列化 字符串=>结构体bool Deserialize(const std::string &str){std::vector<std::string> result;Util::StringSplit(str, SEP, &result);//必须提取出三个变量if (result.size() != 3)return false;_x = atoi(result[0]);_op = result[1][0];_y = atoi(result[2]);return true;}
public:int _x;int _y;char _op;
};// 响应
class Responce
{
public:Responce() : _result(0), _code(0){}// 序列化 结构体->字符串bool Serialize(std::string *outStr){*outStr = "";std::string result_string = std::to_string(_result);std::string code_string = std::to_string(_code);*outStr = result_string + SEP + code_string;return true;}//反序列化 字符串->结构体bool Deserialize(const std::string &str){std::vector<std::string> result;Util::StringSplit(str, SEP, &result);if (result.size() != 2)return false;_result = atoi(result[0]);_code = atoi(result[1]);return true;}
public:int _result;int _code;
};

2. JSON

序列化一般我们不自己操作,可以使用别的封装好的序列化,比如:JSON,ProtocolBuffer,FlatBuffer,DIMBIN

本篇文章介绍json的使用
JSON 的语法规则总结起来有:

  • 数组(Array)用方括号(“[]”)表示。
  • 对象(0bject)用大括号(“{}”)表示。
  • 名称/值对(name/value)组合成数组和对象。
  • 名称(name)置于双引号中,值(value)有字符串、数值、布尔值、null、对象和数组。
  • 并列的数据之间用逗号(“,”)分隔

序列化后可视效果也较好,比如:

{"x":10,"y":22,"op":*
}

代码:

// 请求
class Request
{
public:Request() {}// 结构体=>字符串bool Serialize(std::string *outStr){// Value,一种万能对象,接收任意的kv类型Json::Value root;root["x"] = _x;root["y"] = _y;root["op"] = _op;// 序列化Json::StyledWriter writer;*outStr = writer.write(root);return true;}// 字符串=>结构体bool Deserialize(const std::string &str){Json::Value root;// 反序列化Json::Reader reader;reader.parse(str, root);//提取变量_x = root["x"].asInt();_y = root["y"].asInt();_op = root["op"].asInt();return true;}
public:int _x;int _y;char _op;
};
// 响应
class Responce
{
public:Responce() : _result(0), _code(0){}// 结构体->字符串bool Serialize(std::string *outStr){Json::Value root;root["result"] = _result;root["code"] = _code;// 序列化Json::StyledWriter writer;*outStr = writer.write(root);return true;}bool Deserialize(const std::string &str){Json::Value root;//反序列化Json::Reader reader;reader.parse(str, root);//提取变量_result = root["result"].asInt();_code = root["code"].asInt();return true;}
public:int _result;int _code;
};

二. 初识协议

在网络通信中,客户端,服务器收发数据其实是如下这样的

在这里插入图片描述

我们调用的recv,send等接口,只是将我们定义的缓冲区的数据拷贝到TCP的缓冲区,或者将数据从TCP缓冲区拷贝到上层
TCP是面向字节流的,可以认为,数据是一个字节一个字节传输的
如果,客户端发送一个hello,recv接口会将发送缓冲区的数据一次性拷贝到上层,但可能此时通过网络传输,只传送了hel,服务器的接受缓冲区只有hel,此时recv并没有读取到完整报文,并且我们不知道什么时候读到了完整报文
协议就是为了解决这类问题而诞生的

基于本次网络计算机的案列,简单设计的协议比如,添加长度和\r\n报头
比如:“1 + 1” =>“5"”\r\n"“1 + 1"”\r\n"

解析:通过找到第一个\r\n,获取有效载荷(1 + 1)的长度,再根据长度提取有效载荷

代码如下:

#define HEADER_SEP "\r\n" // 报头分隔符
#define HEADER_SEP_LEN strlen(HEADER_SEP)
// 读取数据,并尝试提取一个完整报文
// 完整报文:"有效载荷长度""\r\n""有效载荷""\r\n"
//inbuffer保存所有读取的数据,package是一个完整报文,需要输出
int ReadPackage(int sock, std::string &inbuffer, std::string *package)
{// 读数据char buffer[1024];int n = recv(sock, buffer, sizeof(buffer) - 1, 0);if (n > 0)buffer[n] = '\0';else if (n == 0)//写端关闭return -1;else if (n < 0)//读取异常return -2;//将本次读取的数据保存inbuffer += buffer;//开始查找报头分隔符size_t start = 0;auto pos = inbuffer.find(HEADER_SEP, start);if (pos == std::string::npos)return 0; //第一个分隔符都没有,不是完整报文//提取长度std::string lenStr = inbuffer.substr(0, pos);int len = Util::toInt(lenStr); // 有效载荷的长度// 完整报文的长度int targetPackageLen = lenStr.size() + len + 2 * HEADER_SEP_LEN;if (inbuffer.size() < targetPackageLen)return 0; //长度不足完整报文// 提取一个完整报文,并输出*package = inbuffer.substr(0, targetPackageLen);inbuffer.erase(0, targetPackageLen);return len;
}

结束语

本篇博客到此结束,感谢看到此处。
欢迎大家纠错和补充
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

相关文章:

【计算机网络学习之路】序列化,反序列化和初识协议

文章目录 前言一. 序列化和反序列化1.自己实现2. JSON 二. 初识协议结束语 前言 本系列文章是计算机网络学习的笔记&#xff0c;欢迎大佬们阅读&#xff0c;纠错&#xff0c;分享相关知识。希望可以与你共同进步。 本篇博文正式开始应用层的学习&#xff0c;首先讲解应用层的…...

亚马逊云科技推出新一代自研芯片

北京——2023 年12月1日 亚马逊云科技在2023 re:Invent全球大会上宣布其自研芯片家族的两个系列推出新一代&#xff0c;包括Amazon Graviton4和Amazon Trainium2&#xff0c;为机器学习&#xff08;ML&#xff09;训练和生成式人工智能&#xff08;AI&#xff09;应用等广泛的工…...

VIT总结

关于transformer、VIT和Swin T的总结 1.transformer 1.1.注意力机制 An attention function can be described as mapping a query and a set of key-value pairs to an output, where the query, keys, values, and output are all vectors. The output is computed as a wei…...

C++11——initializer_list

initializer_list的简介 initializer_list是C11新出的一个类型&#xff0c;正如类型的简介所说&#xff0c;initializer_list一般用于作为构造函数的参数&#xff0c;来让我们更方便赋值 但是光看这些&#xff0c;我们还是不知道initializer_list到底是个什么类型&#xff0c;…...

数学字体 Mathematical fonts

Mathematical fonts 数学字体&#xff1a; ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ \\ \mathcal{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathfrak{ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzRQSZ} \\ \mathbb{ABC…...

Python简单模拟蓝牙车钥匙协议

本文设计一个简单的蓝牙车钥匙协议&#xff0c;协议包含DH密钥协商和基于RSA的身份认证功能&#xff0c;以及防重放与消息完整性验证。 1. 密钥协商过程: - 设定 DH 参数&#xff1a;素数 p 和生成元 g。 - 发送方&#xff08;Alice&#xff09;生成 DH 的私钥 a 并计算公钥 A…...

【Python3】【力扣题】383. 赎金信

【力扣题】题目描述&#xff1a; 题解&#xff1a; 两个字符串ransomNote和magazine&#xff0c;ransomNote中每个字母都在magazine中一一对应&#xff08;顺序可以不同&#xff09;。 即分别统计两个字符串中每个字母出现的次数&#xff0c;ransomNote中每个字母的个数小于等…...

外包搞了6年,技术退步明显......

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近6年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…...

uni-app x生成的安卓包,安装时,提示不兼容。解决方案

找到 manifest.json 进入&#xff1a;源码视图 代码 {"name" : "xxx康养","appid" : "__xxx6","description" : "xxx康养","versionName" : "1.0.12","versionCode" : 100012,&…...

Screenshot To Code

序言 对于GPT-4我只是一个门外汉&#xff0c;至于我为什么要了解screenshot to code&#xff0c;只是因为我想知道&#xff0c;在我不懂前端设计的情况下&#xff0c;能不能通过一些工具辅助自己做一些简单的前端界面设计。如果你想通过此文深刻了解GPT-4或者该开源项目&#…...

SpringBoot 是如何启动一个内置的Tomcat

为什么说Spring Boot框架内置Tomcat 容器,Spring Boot框架又是怎么样去启动Tomcat的?我简单总结下学习过程。 一:简单了解SpringBoot的启动类 我们都知道Spring Boot框架的启动类上是需要使用 @SpringBootApplication 注解标注的, @SpringBootApplication 是一个复合注解…...

《功能磁共振多变量模式分析中空间分辨率对解码精度的影响》论文阅读

《The effect of spatial resolution on decoding accuracy in fMRI multivariate pattern analysis》 文章目录 一、简介论文的基本信息摘要 二、论文主要内容语音刺激的解码任务多变量模式分析&#xff08;MVPA&#xff09;K空间 空间分辨率和平滑对MVPA的影响平滑的具体过程…...

pygame实现贪吃蛇小游戏

import pygame import random# 游戏初始化 pygame.init()# 游戏窗口设置 win_width, win_height 800, 600 window pygame.display.set_mode((win_width, win_height)) pygame.display.set_caption("Snake Game")# 颜色设置 WHITE (255, 255, 255) BLACK (0, 0, 0…...

反序列化漏洞(二)

目录 pop链前置知识&#xff0c;魔术方法触发规则 pop构造链解释&#xff08;开始烧脑了&#xff09; 字符串逃逸基础 字符减少 字符串逃逸基础 字符增加 实例获取flag 字符串增多逃逸 字符串减少逃逸 延续反序列化漏洞(一)的内容 pop链前置知识&#xff0c;魔术方法触…...

【开箱即用】前后端同时开源!周末和AI用Go语言共同研发了一款笔记留言小程序!

大家好&#xff0c;我是豆小匠。 真的是当你在怀疑AI会不会取代人类的时候&#xff0c;别人已经用AI工具加速几倍的生产速度了… 周末体验了和AI共同开发的感受&#xff0c;小项目真的可以一人全干了… 本次实验使用的AI工具有两个&#xff1a;1. GitHub Copilot&#xff08;…...

java对xml压缩

import java.util.*; import java.util.zip.GZIPOutputStream; import java.nio.charset.StandardCharsets; import org.apache.commons.codec.binary.Base64;/*** 模板压缩** param xml 模板xml* return* throws Exception*/public static String businessData(String xml) th…...

GoLang切片

一、切片基础 1、切片的定义 切片&#xff08;Slice&#xff09;是一个拥有相同类型元素的可变长度的序列它是基于数组类型做的一层封装它非常灵活&#xff0c;支持自动扩容切片是一个引用类型&#xff0c;它的内部结构包含地址、长度和容量声明切片类型的基本语法如下&#…...

前端入门(四)Ajax、Promise异步、Axios通信、vue-router路由、组件库

文章目录 AjaxAjax特点 Promise 异步编程&#xff08;缺&#xff09;Promise基本使用状态 - PromiseState结果 - PromiseResult AxiosVue中使用AxiosAxios请求方式getpostput和patchdelete并发请求 Vue路由 - vue-router单页面Web应用&#xff08;single page web application&…...

正则表达式回溯陷阱

一、匹配场景 判断一个句子是不是正规英文句子 text "I am a student" 一个正常的英文句子如上&#xff0c;英文单词 空格隔开 英文单词 多个英文字符 [a-zA-Z] 空格用 \s 表示 那么一个句子就是单词 空格&#xff08;一个或者多个&#xff0c;最后那个单词…...

MATLAB实战 | S函数的设计与应用

S函数用于开发新的Simulink通用功能模块&#xff0c;是一种对模块库进行扩展的工具。S函数可以采用MATLAB语言、C、C、FORTRAN、Ada等语言编写。在S函数中使用文本方式输入公式、方程&#xff0c;非常适合复杂动态系统的数学描述&#xff0c;并且在仿真过程中可以对仿真进行更精…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

表单设计器拖拽对象时添加属性

背景&#xff1a;因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...