应用层协议 序列化

news2024/10/20 4:06:15

自定义应用层协议

例子:网络版本计算器

序列化反序列化

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

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

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

                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\n
    void 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 b
    bool 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 b
        void Serializa(string *message)
        {
            string left = to_string(_data_a);
            string right = to_string(_data_b);
            *message = left + Seq + _oper + Seq + right;
        }
        // a op b
        bool 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 code
        bool 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 b
        bool 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.coloradmin.cn/o/2218980.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python案例小练习——小计算器

文章目录 前言一、代码展示二、运行展示 前言 这是用python实现一个简单的计器。 一、代码展示 def calculate(num1, op, num2):if op "":return float(num1) float(num2)elif op "-":return float(num1) - float(num2)elif op "*":return…

案例分享-优秀蓝色系UI界面赏析

蓝色UI设计界面要提升舒适度&#xff0c;关键在于色彩搭配与对比度。选择柔和的蓝色调作为主色&#xff0c;搭配浅灰或白色作为辅助色&#xff0c;能营造清新、宁静的氛围。同时&#xff0c;确保文字与背景之间有足够的对比度&#xff0c;避免视觉疲劳&#xff0c;提升阅读体验…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…

新书速览|Android智能座舱开发:从源码到实践

《Android智能座舱开发:从源码到实践》 本书内容 《Android智能座舱开发:从源码到实践》是一本专注于Android智能座舱系统开发与优化的实战指南。《Android智能座舱开发:从源码到实践》共9章&#xff0c;第1章从搭建源码编译环境开始&#xff0c;详细指导读者如何下载和编译An…

前端SSR框架(Next、Nuxt)利用宝塔面板部署

1、部署的本质 SSR服务端渲染的框架部署区别于常规的CSR项目的部署&#xff0c;并不是打包之后访问某个文件就行&#xff0c;而是需要在服务器中运行项目之后访问某个地址&#xff0c;无论是基于Vue的Nuxt.js框架还是基于React的Next.js框架道理都是一样的 因此区别于CSR我们…

2024年中国工业大模型行业发展研究报告|附43页PDF文件下载

工业大模型伴随着大模型技术的发展&#xff0c;逐渐渗透至工业&#xff0c;处于萌芽阶段。 就大模型的本质而言&#xff0c;是由一系列参数化的数学函数组成的计算系统&#xff0c;且是一个概率模型&#xff0c;其工作机制是基于概率和统计推动进行的&#xff0c;而非真正的理解…

to_sql报错not all arguments converted during string formatting

报错&#xff1a; DatabaseError: Execution failed on sql SELECT name FROM sqlite_master WHERE typetable AND name?;: not all arguments converted during string formattingb 报错的代码如下&#xff1a; import pymysql import pandas as pd con pymysql.connect(…

如何测量场景的照度和色温?

1、问题背景 在我们平常的工作当中&#xff0c;经常都会使用照度计去测量当前场景的照度和色温&#xff0c;但测量时照度计具体该放在什么位置呢&#xff1f; 是和被测物体表面平行放置&#xff0c;还是和摄像头镜头位置平齐放置呢&#xff1f;本文将从照度、色温的概念出发&am…

ntfs MFT损坏(ntfs文件系统故障)导致oracle异常恢复---惜分飞

客户虚拟化环境,由于断电,启动数据库报ORA-01157错误,通过操作系统层面查看,发现文件是存在的,但是dbv检测报不可访问 感觉是文件系统损坏了,尝试把该文件拷贝到其他磁盘 查看操作系统事件,确认是ntfs文件系统的MFT损坏 基于这种情况,通过文件系统恢复工具进行恢复该文件…

【Java】Java 的反射机制(二):类的加载(拓展)

Java 的反射机制&#xff08;二&#xff09;&#xff1a;类的加载&#xff08;拓展&#xff09; 1.类的加载过程1.1 Java 内存分析1.2 类的加载过程1.3 类的加载与 ClassLoader 的理解1.4 什么时候会发生类的初始化 2.类加载器 1.类的加载过程 1.1 Java 内存分析 1.2 类的加载…

观测云 AI 助手上线:智能运维,从此触手可及!

在当前的云原生时代&#xff0c;运维的复杂性和数据的爆炸式增长给企业带来了前所未有的挑战。为了帮助企业高效应对这些挑战&#xff0c;观测云自豪地推出了 AI 助手——智能化的运维助手&#xff0c;让每位用户都能轻松驾驭复杂的可观测性场景。 01 你身边的 PE 助手&#x…

vs2022配置opencv静态库

本文将在windows10环境下&#xff0c;vs2022Cmake3.24.4编译opencv静态库&#xff0c;包括win32-release,win32-debug, x64-release, x64-debug四种&#xff1b; 文章内容有点长&#xff0c;请耐心看下去。 一、安装VS2022 下载链接&#xff1a;https://visualstudio.micros…

【设计模式系列】装饰器模式

目录 一、什么是装饰器模式 二、装饰器模式中的角色 三、装饰器模式的典型应用场景 四、装饰器模式在BufferedReader中的应用 一、什么是装饰器模式 装饰器模式是一种结构型设计模式&#xff0c;用于在不修改对象自身的基础上&#xff0c;通过创建一个或多个装饰类来给对象…

海南聚广众达电子商务咨询有限公司靠谱吗怎么样?

在当今这个数字化浪潮席卷全球的时代&#xff0c;抖音电商以其独特的魅力成为了众多商家争相入驻的新蓝海。而在这片浩瀚的电商海洋中&#xff0c;如何找到一家既专业又可靠的合作伙伴&#xff0c;成为了众多商家心中的一大难题。今天&#xff0c;我们就来深入剖析一下海南聚广…

模电基础(放大电路的频率响应+multisim)

目录 1.频率响应的基本概念 1.1频率响应的基本概念 1.1.1高通滤波器 1.1.2低通滤波器 1.1.3波特图 1.1.4multisim仿真 1.2晶体管高效等效模型 1.2.1晶体管的混合π模型 1.2.2晶体管电流放大倍数的频率响应 ​1.3单管放大电路的频率响应 1.3.1单管共射放大电路的频率响…

如何查看默认网关地址:详细步骤

在日常的网络配置与故障排查中&#xff0c;了解并正确查看默认网关地址是一项基础且至关重要的技能。默认网关是连接本地网络与外部网络&#xff08;如互联网&#xff09;的关键节点&#xff0c;它扮演着数据包转发的重要角色。无论是家庭网络、办公室网络还是更复杂的网络环境…

Threejs 实现3D 地图(01)创建基本场景

"d3": "^7.9.0", "three": "^0.169.0", "vue": "^3.5.10" <script setup> import { onMounted,ref } from vue import * as THREE from three import * as d3 from "d3"; //莫开托坐标 矫正地图…

vue综合指南(二)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Vuet篇专栏内容:vue综合指南(二) 目录 21、介绍虚拟DOM 22、vue生命周期的理解 23、vue父组件向子组件传递数据…

sql高级

数据库的范式 为了建立冗余较小、结构合理的数据库&#xff0c;设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。 范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库&#xff0c;必须满足一定的范式。实际上&#xff0c;数据库范式…

基于SSM+微信小程序的打印室预约管理系统(打印2)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的打印室预约管理系统实现了管理员和用户两个角色。 1、管理员功能有个人中心&#xff0c;用户管理&#xff0c;附近打印店管理&#xff0c;文件打印管理&#xff0c;当…