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

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

文章目录

  • 一、应用层
    • 1、协议
    • 2、序列化 && 反序列化
    • 3、通过Json库进行数据的序列化 && 反序列化
      • Json::Value类
      • Json::Reader类
      • Json::Writer类
  • 二、为什么read、write、recv、send和Tcp支持全双工?
    • 发数据的本质:
    • tcp支持全双工通信的原因:
    • 为什么IO函数要阻塞?
    • 其他:
      • 因为面向字节流,可能读取不了一个完成的请求,那如何保证在主机中保证处理的是一个完整的请求?
      • 因为面向字节流,可能读取不了一个完成的请求,那如何保证在主机中保证处理的是一个完整的请求?

一、应用层

1、协议

  • 协议本质是一种约定。
  • 协议就是双方约定好的结构化数据。

2、序列化 && 反序列化

在用户在网络中发送的信息类型不都是字符串,有可能是整型,浮点数,自定义类型等等,将不同的类型通过网络发送给另外一个客户端,然后进行识别明显是比较困难的,为了解决这种事情,我们把发送的消息进行序列化和反序列化来对信息进行封装和解封。

image-20240925190644793

3、通过Json库进行数据的序列化 && 反序列化

Json::Value类

  • operator[]:通过键名或索引访问JSON对象中的元素。
  • append:向JSON数组中添加元素。
  • asStringasIntasFloatasBool等:将Json::Value对象转换为不同的数据类型。
  • type():获取Json::Value对象的类型。
    // 创建一个Json::Value 对象
    Json::Value root;

    // 通过键值访问Json对象元素,如果没有键值对应的元素则新建
    root["name"] = "zhangsan";
    root["age"] = 18;
    root["year" ] = 2024;

    // 向数组中添加键值对
    // 创建一个Json::Value对象,并初始化为数组类型
    Json::Value root(Json::arrayValue);
    // 使用append方法向数组中添加元素
    root.append("Hello"); // 添加一个字符串
    root.append(123);     // 添加一个整数
    root.append(45.67);   // 添加一个浮点数

    // 将Json::Value对象转换为不同的数据类型
    // asString、asInt、asFloat、asBool等
    int age = root["age"].asInt();
    std::string name = root["name"].asString();
    // 获取Json::Value对象的类型
    // Null:表示JSON中的null值。
    // String:表示JSON中的字符串值。
    // Number:表示JSON中的数字值,这通常包括整数和浮点数。不过,在某些实现中,可能会进一步区分整数(Int)和浮点数(Float或Double)。
    // Boolean:表示JSON中的布尔值(true或false)。
    // Array:表示JSON中的数组,数组可以包含多个JSON值,这些值的类型可以不同。
    // Object:表示JSON中的对象,对象由键值对组成,其中键是字符串,值是任意的JSON值。
    // ...
    Json::ValueType type = root.type();
    
    // 输出,测试 
    Json::FastWriter writer;
    std::string str = writer.write(root);
    std::cout << str << std::endl;

Json::Reader类

用于将JSON格式的字符串解析为Json::Value对象。

  • parse:解析JSON字符串,并将其存储在Json::Value对象中。
// JSON格式的字符串
    std::string jsonStr = R"({"name": "John Doe", "age": 30, "is_student": false, "scores": [90, 85, 95]})";

    // 创建一个Json::Value对象来存储解析后的JSON数据
    Json::Value root;

    // 创建一个Json::Reader对象来解析JSON字符串
    Json::Reader reader;

    // 使用parse方法解析JSON字符串
    bool parsingSuccessful = reader.parse(jsonStr, root);

    // 检查解析是否成功
    if (!parsingSuccessful)
    {
        // 如果解析失败,输出错误信息
        std::cout << "Failed to parse JSON"
                  << std::endl
                  << reader.getFormattedErrorMessages() << std::endl;
        return 1;
    }

    // 解析成功后,可以使用root对象来访问JSON数据
    std::string name = root["name"].asString();
    int age = root["age"].asInt();
    bool isStudent = root["is_student"].asBool();

    // 访问数组中的元素
    Json::Value scores = root["scores"];
    for (int i = 0; i < scores.size(); ++i)
    {
        std::cout << "Score " << i + 1 << ": " << scores[i].asInt() << std::endl;
    }

    // 输出一些基本信息
    std::cout << "Name: " << name << std::endl;
    std::cout << "Age: " << age << std::endl;
    std::cout << "Is Student: " << std::boolalpha << isStudent << std::endl;

Json::Writer类

  • 功能:Json::Writer是一个抽象基类,用于将Json::Value对象序列化为JSON格式的字符串。通常不会直接使用,而是使用其子类如Json::StyledWriter或Json::FastWriter。
  • 子类
    • Json::StyledWriter:生成格式化的JSON字符串,易于阅读。
    • Json::FastWriter:生成紧凑的JSON字符串,没有额外的空格和换行符。
    Json::Value root;
    root["name"] = "zhangsan";
    root["age"] = 18;
    root["year"] = 2024;

    Json::FastWriter fast_write;
    Json::StyledWriter styledwriter;

    std::string str1 = fast_write.write(root);
    std::cout << str1 << std::endl;
    std::cout << "------------------------------" << std::endl;
    std::string str2 = styledwriter.write(root);
    std::cout << str2 << std::endl;

image-20240925235011003

二、为什么read、write、recv、send和Tcp支持全双工?

image-20240925191138356

  • 一个文件描述符fd,代表一个连接。一个连接,有两个缓冲区,发送缓冲区和接收缓冲区
  • read、write、send、recv**本质都是拷贝函数**。

发数据的本质:

从发送方的发送缓冲区把数据通过协议栈和网络拷贝给接收方的接收缓冲区。

tcp支持全双工通信的原因:

有两个缓冲区,读写不受到冲突。

(传输控制协议!什么时候发?发多少?出错了怎么办?均有tcp决定。)

为什么IO函数要阻塞?

本质就是在维护同步关系!

其他:

  • 网络层、传输层 属于 os。
  • 面向字节流:客户端发的,不一定全部是服务器收的。— 也就是说客户端可能发送的不是一个完整报文

因为面向字节流,可能读取不了一个完成的请求,那如何保证在主机中保证处理的是一个完整的请求?

  • 网络层、传输层 属于 os。
  • 面向字节流:客户端发的,不一定全部是服务器收的。— 也就是说客户端可能发送的不是一个完整报文

因为面向字节流,可能读取不了一个完成的请求,那如何保证在主机中保证处理的是一个完整的请求?

手动分割完整的报文。


http://www.kler.cn/news/328666.html

相关文章:

  • 【Java数据结构】 ArrayList 顺序表
  • Android-Handle消息传递和线程通信
  • LeetCode 面试经典150题 66.加一
  • 【数据类型】C和C++的区别
  • 【C#生态园】探索地理信息系统软件套件与库:功能、API和应用
  • CSS | CSS中强大的margin负边距
  • 深度学习中的卷积神经网络
  • Ubuntu安装Docker和Docker Compose
  • 高性价比PCB分板机高速主轴SycoTec 4025 HY
  • LeetCode 面试经典150题 172.阶乘后的零
  • PCL 最远点采样(FPS)
  • 微服务SpringSession解析部署使用全流程
  • 10.数据结构与算法-线性表的应用(线性表与有序表的合并)
  • 【K8S系列】深入解析 Kubernetes 网络策略(二)
  • Redis篇(Java操作Redis)
  • 微服务JSR303解析部署使用全流程
  • tailwindcss group-hover 不生效
  • Spring Boot驱动的足球青训俱乐部管理解决方案
  • 鹏哥C语言62---第9次作业:函数递归练习
  • 2025 年 IT 前景:机遇与挑战并存,人工智能和云计算成重点
  • 【Android 源码分析】Activity生命周期之onPause
  • local minima 的问题如何解决
  • .Net 基于IIS部署blazor webassembly或WebApi
  • 用Python+flask+mysql等开发的Excel数据资产落地工具
  • 【一文读懂】C#如何实现通用的排序功能
  • 车辆重识别(利用扩散模型合成有效数据进行行人再识别预训练)论文阅读2024/9/27
  • 【树莓派系列】树莓派首次开机配置
  • LeetCode 面试经典150题 50.Pow(x,n)
  • VMware 设置静态IP
  • 鸿蒙开发(NEXT/API 12)【硬件(取消注册智慧出行连接状态的监听)】车载系统