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

文章目录

一、应用层

1、协议

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

2、序列化 && 反序列化

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

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

Json::Value类

  • operator[]:通过键名或索引访问JSON对象中的元素。
  • append:向JSON数组中添加元素。
  • asStringasIntasFloatasBool等:将Json::Value对象转换为不同的数据类型。
  • type():获取Json::Value对象的类型。
cpp 复制代码
    // 创建一个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对象中。
cpp 复制代码
// 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字符串,没有额外的空格和换行符。
cpp 复制代码
    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;

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

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

发数据的本质:

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

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

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

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

为什么IO函数要阻塞?

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

其他:

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

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

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

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

手动分割完整的报文。

相关推荐
-SGlow-20 分钟前
MySQL相关概念和易错知识点(3)(表内容的CURD、内置函数)
linux·运维·服务器·数据库·mysql
永远向阳而生1 小时前
【Linux】磁盘存储+文件系统简介
linux
君不见~2 小时前
Windows 10 WSL&Ubuntu 22.04 安装并迁移到 F 盘
linux·ubuntu·wsl迁移盘符·wsl迁移
PanYu——BJ2 小时前
CentOS Nginx 1.13.9 部署文档
linux·nginx·centos
UQWRJ2 小时前
菜鸟教程Linux ViVimYumApt笔记
linux·运维·笔记
Ray Song2 小时前
Linux DNS解析3 -- DNS解析代理配置使用
linux·dns解析·dns代理
sz66cm3 小时前
Linux基础 -- 内核快速向用户态共享内核变量方案之ctl_table
linux·运维·服务器
努力一点9483 小时前
ubuntu22.04系统入门 linux入门(二) 简单命令 多实践以及相关文件管理命令
linux·运维·服务器·人工智能·gpu算力
UU_Yang4 小时前
Linux跑后台服务
linux·运维·服务器
kfepiza5 小时前
vim的`:q!` 与 `ZQ` 笔记250729
linux·笔记·编辑器·vim