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

【计算机网络】应用层序列化

目录

  • 一、序列化和反序列化
  • 二、重新理解 read、write、recv、send 和 tcp 为什么支持全双工
  • 三、Jsoncpp

一、序列化和反序列化

如果我们要实现一个网络版的加法器,需要把客户端的数据发给服务端,由服务端处理数据,再把处理结果发给客户端。

方案:

  • 定义结构体来表示我们需要交互的信息
  • 发送数据时将这个结构体按照一个规则转换成字符串, 接收到数据的时候再按照相同的规则把字符串转化回结构体。这个过程叫做 “序列化” 和 “反序列化”

只要保证一段发送的数据,另一端接收能够正确解析就行,这种约定就是应用层协议。

在这里插入图片描述
发送一条聊天消息,由3个字符串组成。序列化,将消息由多变一,方便传输。网络通信不需要关注具体是什么,只要传输的是字节流就行。反序列化,将消息由一变多,方便上层处理。

序列化:

#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include <fstream>

using namespace std;

struct stu
{
    string name;
    int age;
    double weight;
};

int main()
{
    // 结构化数据
    struct stu zs = {"张三", 18, 72};

    // 转换为字符串
    Json::Value root;
    root["name"] = zs.name;
    root["age"] = zs.age;
    root["weight"] = zs.weight;

    //Json::FastWriter writer;
    Json::StyledWriter writer;
    string str = writer.write(root);

    ofstream out("out.txt");
    if(!out.is_open())
    {
        cout << str;
        return 1;
    }
    out << str;
    out.close();
    
    return 0;
}

写入文件:
在这里插入图片描述

反序列化:

#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include <fstream>

using namespace std;

struct stu
{
    string name;
    int age;
    double weight;

    void Debug()
    {
        cout << name << endl;
        cout << age << endl;
        cout << weight << endl;
    }
};

int main()
{
    ifstream in("out.txt");
    if(!in.is_open()) return 1;
    char buffer[1024];
    in.read(buffer, sizeof(buffer));
    in.close();

    // 反序列化
    string json_string = buffer;
    Json::Value root;
    Json::Reader reader;
    bool res = reader.parse(json_string, root);
    (void)res;

    struct stu zs;
    zs.name = root["name"].asString();
    zs.age = root["age"].asInt();
    zs.weight = root["weight"].asDouble();

    zs.Debug();

    return 0;
}

在这里插入图片描述

二、重新理解 read、write、recv、send 和 tcp 为什么支持全双工

先回顾下read、write这些系统调用是怎么读、写的:
在这里插入图片描述
用户发送一段数据先到C缓冲区,然后通过系统调用交给操作系统的管理区,发送的数据到task_struct,根据fd在文件描述符表找到位置,再指向指定的struct file,然后把数据传输到缓冲区,缓冲区会把数据刷新到磁盘中。

在这里插入图片描述
用户在主机A发送消息给另一个用户主机B,消息序列化后通过系统调用到发送缓冲区,然后经过网络的每个分层到另一个主机,再自底向上到接收缓冲区,然后通过系统调用到应用层,再序列化变成用户可看到的消息。注意:系统调用让数据从用户层到发送缓冲区,或者从接收缓冲区到用户层,这个过程都是拷贝。所以,read、write等系统调用本质是拷贝函数。

tcp发送数据,其实是把数据从自己的发送缓冲区拷贝到接收方的接收缓冲区,发送缓冲区和接收缓冲区都是在各自的操作系统里,所以本质是双方的操作系统在进行通信。通信就是在拷贝数据。

如果接收缓冲区没有数据,那么read\recv系统调用会阻塞,这里的阻塞其实是用户层在进行同步,即发送方发数据,接收方才收数据。

那么tcp为什么支持全双工?因为双方都是一对发送缓冲区和接收缓冲区。为什么系统调用也支持全双工?因为fd既可以读,又可以写,就是有一对发送缓冲区和接收缓冲区。

三、Jsoncpp

介绍:Jsoncpp 是一个用于处理 JSON 数据的 C++ 库。它提供了将 JSON 数据序列化为字符串以及从字符串反序列化为 C++ 数据结构的功能。Jsoncpp 是开源的,广泛用于各种需要处理 JSON 数据的 C++ 项目中

特性:

  • 简单易用:Jsoncpp 提供了直观的 API,使得处理 JSON 数据变得简单
  • 高性能:Jsoncpp 的性能经过优化,能够高效地处理大量 JSON 数据
  • 全面支持:支持 JSON 标准中的所有数据类型,包括对象、数组、字符串、数字、布尔值和 null
  • 错误处理:在解析 JSON 数据时,Jsoncpp 提供了详细的错误信息和位置,方便开发者调试

序列化函数:toStyledString、StreamWriter 和 FastWriter
反序列化函数:Json::Reader 和 parseFromStream


http://www.kler.cn/a/307590.html

相关文章:

  • 94个属于一区且接受医工交叉领域投稿的期刊汇总|个人观点·24-11-13
  • 大数据技术之HBase中的HRegion
  • 在Flutter中,禁止侧滑的方法
  • 矩阵的各种计算:乘法、逆矩阵、转置、行列式等——基于Excel实现
  • RHCE的学习(16)(shell脚本编程)
  • LLM之模型评估:情感评估/EQ评估/幻觉评估等
  • 【每日一题】LeetCode 2398.预算内的最多机器人数目(滑动窗口、数组、二分查找、前缀和、堆(优先队列))
  • 多层建筑能源参数化模型和城市冠层模型的区别
  • Typora2024最新版破解方法(亲测可用)
  • CentOS配置python版本管理工具pyenv
  • Maven 常见问题以及常用命令
  • 函数题 6-2 多项式求值【PAT】
  • UVA-225 黄金图形 题解答案代码 算法竞赛入门经典第二版
  • 电脑浏览器访问华为路由器报错,无法访问路由器web界面:ERR_SSL_VERSION_OR_CIPHER_MISMATCH 最简单的解决办法!
  • 代码随想录打卡Day32
  • Unity 使用Spine动画切换时有残影
  • VSCode创建C++项目和编译多文件
  • java发邮件内容含表格实现方法?如何配置?
  • sqlgun新闻管理系统
  • 本地部署大语言模型详细操作步骤
  • Y电容(安规电容)的作用是什么?
  • 【C++】queue和priority_queue
  • Linux:进程(一)
  • 无人机建模详解!!!
  • [Leetcode LCR 154][Medium]-复杂链表的复制-链表
  • JSON数组