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

应用层协议 序列化

自定义应用层协议

例子:网络版本计算器

序列化反序列化

序列化:将消息,昵称,日期整合成消息-昵称-日期

反序列化:消息-昵称-日期->消息,昵称,日期

在序列化中,定义一个结构体

                struct Message{string message;string name;string data;};

用这个结构体进行通信,就是一种协议,约定好的一种结构化字段就叫做协议

再比如

 struct complate{int num1;int num2;char  oper;
}

序列化:将协议规定的结构化数据转换成字符串字节流 为什么?发送效率变高

反序列化:将字符串字节流转换成结构化数据 为什么?方便与提取有效字段

协议定制procotol

1.直接传递struct

可以,但使用范围很小

2.自己实现序列化反序列化

前备

客户端发送到服务端,send/write函数其实是将自己的缓冲区拷贝到发送的缓冲区,并没有经过网络。发送缓冲区的数据,发多少,怎么发,出错怎么办,一致由Tcp协议决定,Tcp实际通信的时候,是由双方操作系统之间进行通信,同理read/recv也是拷贝函数,将接收缓冲区拷贝到用户缓冲区。

既然send/write是拷贝函数,也就是说当接收缓冲区为空,发送缓冲区为满,双方进程都会被阻塞住。

Tcp为什么是全双工通信协议?

当客户端进行发送,服务端进行接收的同时,服务端也可以进行发送,客户端进行接收

当我们发送helloworld的时候,对方一定收到helloworld吗?

不一定,当服务端的接受缓冲区只剩5个字节了,客户端以为自己发了10个字节,但事实上服务端此时只能读取到5个字节。这种特点我们叫做面向字节流

所以我们得明确报文和报文之间的边界

我们要解决的问题

a.解决结构化数据的序列化和反序列化

本质上是把结构化字段转换为字符串

b.解决用户区分报文边界问题

加入\n进行判断

namespace Proc_wrok
{const string Seq = " ";const string LineSep = "\n";//a op b//len\na op b\nvoid Encode(string & message){int len=message.size();message=to_string(len)+LineSep+message+LineSep;}//len\na op b\n//len//len\n//len\na op b//len\na op b\n//len\na op b\nlen\n//a op bbool Decode(string & Package,string * message){auto LineSepPos=Package.find("\n");if(LineSepPos==string::npos) return false;int messagelen=stoi(Package.substr(0,LineSepPos));int lensize=(Package.substr(0,LineSepPos)).size();//没有完整的报文int total_size=messagelen+LineSep.size()*2+lensize;if(Package.size()<total_size) return false;  //有完整的报文*message=Package.substr(LineSepPos+LineSep.size(),messagelen);//cout<<"有完整的报文:"<<*message<<endl;Package.erase(0,total_size);return true;}class Request{public:Request() {}Request(int data_a, int data_b, char oper): _data_a(data_a), _data_b(data_b), _oper(oper){}void PrintDebug(){cout << "[" << _data_a << "]"<< _oper<< "[" << _data_b << "]"<< "=?" << endl;}void testDebug(){_data_a++;_data_b++;}// a op bvoid Serializa(string *message){string left = to_string(_data_a);string right = to_string(_data_b);*message = left + Seq + _oper + Seq + right;}// a op bbool DesSerializa(string &message){auto left = message.find(Seq);if (left == string::npos)return false;auto right = message.rfind(Seq);if (right == string::npos)return false;string numa = message.substr(0, left);string oper = message.substr(left + 1, right - (left + 1));if (oper.size() != 1){cout << "Sep error" << endl;return false;}string numb = message.substr(right + 1);_data_a = stoi(numa);_data_b = stoi(numb);_oper = oper[0];return true;}int GetA(){return _data_a;}int GetB(){return _data_b;}char GetOper(){return _oper;}private:int _data_a;int _data_b;char _oper;};class Result{public:Result() {}Result(int result, int code): _result(result), _code(code){}void Serializa(string *message){string left = to_string(_result);string right = to_string(_code);*message = left + Seq + right;}// result codebool DesSerializa(string &message){auto mid = message.find(Seq);if (mid == string::npos)return false;string result = message.substr(0, mid);string code = message.substr(mid + 1);_result = stoi(result);_code = stoi(code);return true;}int GetResult(){return _result;}int GetCode(){return _code;}private:int _result;int _code;};}

3.引入成熟的序列化反序列化

JSON

sudo yum install jsoncpp-devel 安装Jsoncpp库

JSON 版本的序列化与反序列化

void Serializa(string *message){Json::Value root;Json::FastWriter writer;root["_data_a"]=_data_a;root["_data_b"]=_data_b;root["_oper"]=_oper;*message=writer.write(root);}// a op bbool DesSerializa(string &message){Json::Value root;Json::Reader reader;bool retbool=reader.parse(message,root);_data_a=root["_data_a"].asInt();_data_b=root["_data_b"].asInt();_oper=(char)(root["_oper"].asInt());return retbool;}

http://www.lryc.cn/news/463760.html

相关文章:

  • 【HAD】Half-Truth: A Partially Fake Audio Detection Dataset
  • OpenAI Prompt generation - 生成和优化Prompt的Prompt
  • Android技术探索:深入解析Android组件
  • 使用R-GCN处理异质图ACM的demo
  • 征程 6E DISPLAY 功能介绍及上手实践
  • 安卓窗口wms/input小知识NO_INPUT_CHANNEL剖析
  • 【2024最新版】Win10下 Java环境变量配置----适合入门小白
  • Servlet 生命周期详解及案例演示(SpringMVC底层实现)
  • 2024 kali系统2024版本,可视化界面汉化教程(需要命令行更改),英文版切换为中文版,基于Debian创建的kali虚拟机
  • 深入理解 CMake 中的 INCLUDE_DIRECTORIES 与 target_include_directories
  • 【不知道原因的问题】java.lang.AbstractMethodError
  • 分布式篇(分布式事务)(持续更新迭代)
  • [Linux] 逐层深入理解文件系统 (2)—— 文件重定向
  • html+css+js实现Badge 标记
  • 纯css 轮播图片,鼠标移入暂停 移除继续
  • iOS GCD的基本使用
  • 如何设计开发RTSP直播播放器?
  • Java基础系列-一文搞懂自定义排序
  • 扫普通链接二维码打开小程序
  • 计算机储存与分区
  • OpenCV之换脸技术:一场面部识别的奇妙之旅
  • Linux学习笔记9 文件系统的基础
  • Android OpenGL粒子特效
  • 5 -《本地部署开源大模型》在Ubuntu 22.04系统下ChatGLM3-6B高效微调实战
  • dpkg:错误:另外一个进程已经为dpkg前端锁加锁
  • 基于SSM服装定制系统的设计
  • RK3588开发笔记-usb3.0 xhci-hcd控制器挂死问题解决
  • 深入解析TCP/IP协议:网络通信的基石
  • 基于微信小程序的汽车预约维修系统(lw+演示+源码+运行)
  • wifi、热点密码破解 - python