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

Linux--序列化与反序列化

序列化

序列化是指将数据结构或对象状态转换成可以存储或传输的格式的过程。在序列化过程中,对象的状态信息被转换为可以保持或传输的格式(如二进制、XML、JSON等)。序列化后的数据可以被写入到文件、数据库、内存缓冲区中,或者通过网络发送到另一个系统。

序列化的主要目的包括:

  • 持久化:将对象状态保存到存储系统中,以便程序在重新启动时能够重新加载这些数据。
  • 网络传输:在分布式系统中,对象需要通过网络发送到其他节点,序列化是实现这一点的关键步骤。
  • 数据交换:不同的应用程序或系统之间可能需要交换数据,序列化提供了一种标准化的数据格式。

反序列化

反序列化是序列化的逆过程,即将序列化后的数据(如二进制、XML、JSON等)恢复成原始的数据结构或对象状态。在反序列化过程中,原始的数据格式被解析并重新构建成原始对象或数据结构。

反序列化的主要目的是:

  • 恢复对象状态:从存储系统或网络接收的数据中恢复对象的状态。
  • 数据使用:在应用程序中使用反序列化后的数据。

JSON

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,但是JSON是独立于语言的,许多编程语言都有解析JSON的库,因此JSON成为了现代互联网中数据交换的标准格式之一。

Jsoncpp

Jsoncpp是一个开源的C++库,主要用于解析和生成JSON数据格式。

安装方式:
在这里插入图片描述

特点:

  • 轻量级:Jsoncpp具有很小的代码体积和低的内存占用,非常适合嵌入式系统或资源受限的环境。
  • 跨平台:Jsoncpp可以在多种操作系统上运行,包括Windows、Linux、Mac等。
  • 简单易用:Jsoncpp提供了简洁的API,使得解析和生成JSON数据变得非常容易。开发人员可以通过简单的函数调用来实现JSON数据的读取、修改和生成。
  • 高性能:Jsoncpp采用了高效的算法和数据结构,提供了快速的JSON解析和生成功能。
  • 可靠稳定:Jsoncpp经过广泛的测试和使用,已经成为一个成熟的库,具有良好的稳定性和可靠性。

核心功能:

Jsoncpp的核心数据结构是Json::Value类,它表示JSON数据的各种类型,包括对象、数组、字符串、数字等。通过Json::Value类及其相关方法,开发者可以直观地操作JSON数据,无需关注复杂的内部实现细节。

Jsoncpp还提供了几个重要的类来支持JSON数据的解析和生成,包括:

Json::Reader:用于将JSON字符串或文件解析成Json::Value对象。
Json::Writer:(及其子类如Json::FastWriter、Json::StyledWriter等):用于将Json::Value对象序列化为JSON字符串。

在这里插入图片描述

示例:网络计算器

实现一个服务器版的计算器,客户端将要要计算的两个数发送到服务端,服务端计算好将结果返回给客户端;

期间,我们会用一种结构体存储对应的计算的两个数以及符号;数据通过序列化发送到服务端,服务端需要将字符串反序列化解析得到数据;

Socket.hpp

#include <iostream>
#include <string>
#include <functional>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <pthread.h>
#include <sys/types.h>
#include <memory>
#include "InetAddr.hpp"
#include "Log.hpp"namespace socket_ns
{class Socket;const static int gbacklog=8;//默认最大连接数using socket_sptr=std::shared_ptr<Socket>;//套接字指针enum{SOCKET_ERROR = 1,BIND_ERROR,LISTEN_ERROR,USAGE_ERROR};//在基类创建一系列虚函数,只要派生类能用到就在这里创建class Socket{public:virtual void CreateSocketOrDie() =0; //创建套接字virtual void BindSocketOrDie(InetAddr& addr) =0;  //绑定套接字virtual void ListenSocketOrDie()=0; //监听套接字virtual socket_sptr Accepter(InetAddr* addr) =0; //接受客户端virtual bool Connector(InetAddr &addr) = 0; //连接客户端virtual int SockFd() = 0; //获取Sockfdvirtual int Recv(std::string *out) = 0; //接收对方信息virtual int Send(const std::string &in) = 0; //发送给对方信息public://创建监听套接字,将一系列操作细分化,直接引用对应函数直接创建void BuildListenSocket(InetAddr& addr){CreateSocketOrDie();BindSocketOrDie(addr);ListenSocketOrDie();}bool BuildClientSocket(InetAddr &addr){CreateSocketOrDie();return Connector(addr);}};class TcpSocket : public Socket{public:TcpSocket(int sockfd=-1):_sockfd(sockfd){}void CreateSocketOrDie() override  //override明确的重写基类函数{_sockfd=socket(AF_INET,SOCK_STREAM,0);if(_sockfd<0){LOG(FATAL, "socket error");exit(SOCKET_ERROR);}LOG(DEBUG, "socket create success, sockfd is : %d\n", _sockfd);}void BindSocketOrDie(InetAddr& addr) override{struct sockaddr_in local;memset(&local, 0, sizeof(local));local.sin_family = AF_INET;local.sin_port = htons(addr.Port());local.sin_addr.s_addr = inet_addr(addr.Ip().c_str());int n=bind(_sockfd,(struct sockaddr*)&local,sizeof(local));if (n < 0){LOG(FATAL, "bind error");exit(BIND_ERROR);}LOG(DEBUG, "bind success, sockfd is : %d\n", _sockfd);}void ListenSocketOrDie() override{int n=listen(_sockfd,gbacklog);if (n < 0){LOG(FATAL, "listen error");exit(LISTEN_ERROR);}LOG(DEBUG, "listen success, sockfd is : %d\n", _sockfd);}socket_sptr Accepter(InetAddr* addr) override{struct sockaddr_in peer;socklen_t len=sizeof(peer);int sockfd = accept(_sockfd,(struct sockaddr*)&peer,&len);if (sockfd < 0){LOG(WARNING, "accept error\n");return nullptr;}*addr=peer;socket_sptr sock=std::make_shared<TcpSocket>(sockfd);return sock;}virtual bool Connector(InetAddr& addr){struct sockaddr_in server;memset(&server,0,sizeof(server));server.sin_family=AF_INET;server.sin_addr.s_addr=inet_addr(addr.Ip().c_str());server.sin_port=htons(addr.Port());int n=connect(_sockfd,(struct sockaddr*)&server,sizeof(server));if (n < 0){std::cerr << "connect error" << std::endl;return false;}return true;}int Recv(std::string *out) override{char inbuffer[1024];ssize_t n = recv(_sockfd,inbuffer,sizeof(inbuffer)-1,0);if (n > 0){inbuffer[n] = 0;*out += inbuffer; // 接收次数可能不只一次,一般是多次的,}return n;}int Send(const std::string &in) override{int n = send(_sockfd,in.c_str(),in.size(),0);return n;}int SockFd() override{return _sockfd;}~TcpSocket(){}private:int _sockfd;};
}

在这里插入图片描述

ProToCol.hpp

主要是发出请求时将数据序列化和接收数据时反序列化;服务端响应时接收数据的反序列化和发送结果时序列化;

#pragma once 
#include <iostream>
#include <string>
#include<unistd.h>
#include<memory>
#include<jsoncpp/json/json.h>namespace protocol_ns
{// 协议的样子:// 报文 = 报头+有效载荷// "有效载荷的长度"\r\n"有效载荷"\r\nconst std::string SEP= "\r\n";// 解决TCP的粘报问题,TCP 读取不全的问题std::string Encode(const std::string &json_str){int json_str_len = json_str.size(); //有效载荷的长度std::string proto_str = std::to_string(json_str_len); //转为stringproto_str += SEP; //+ 分隔符proto_str += json_str;// + 数据字符串proto_str += SEP;// + 分隔符return proto_str; //返回一个报文}//将报文分析出数据字符串出来std::string Decode(std::string &inbuffer){auto pos = inbuffer.find(SEP); //找到分隔符的位置if (pos == std::string::npos)return std::string();std::string len_str = inbuffer.substr(0, pos);//前头的有效数据长度的字符串if (len_str.empty())return std::string();int packlen = std::stoi(len_str);//记录数据字符串的实际长度(传递时的差错主要出在这里)int total = packlen + len_str.size() + 2 * SEP.size(); //报文总长度if (inbuffer.size() < total)return std::string();std::string package = inbuffer.substr(pos + SEP.size(), packlen); //取出数据字符串inbuffer.erase(0, total); //删除掉原先的报文return package;}//请求将我们的数据序列化和反序列化(客户端)    class Request{public:Request(){}Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper){}   //序列化:将结构体数据转换为字符串bool Serialize(std::string* out){Json::Value root; //Json::Value: Json格式的值root["x"] = _x;root["y"] = _y;root["oper"] = _oper;Json::FastWriter writer;*out=writer.write(root); //将Json值转换为字符串return true;}//反序列化:将字符串转换为结构体数据bool DeSerialize(const std::string& in){Json::Value root;Json::Reader reader;//解析字符串bool res=reader.parse(in,root);//将字符串转为Json值,存放于root中if (!res)return false;//再将Json值转为结构体数据_x = root["x"].asInt();_y = root["y"].asInt();_oper = root["oper"].asInt();return true;}public:int _x;int _y;char _oper; //操作符 _x 加减乘除 _y};//将结果序列化和反序列化(服务端)class Response{public:Response(){}Response(int result, int code) : _result(result), _code(code){}bool Serialize(std::string *out){// 转换成为字符串Json::Value root;root["result"] = _result;root["code"] = _code;Json::FastWriter writer;// Json::StyledWriter writer;*out = writer.write(root);return true;}bool Deserialize(const std::string &in){Json::Value root;Json::Reader reader;bool res = reader.parse(in, root);if (!res)return false;_result = root["result"].asInt();_code = root["code"].asInt();return true;}public:int _result; // 结果int _code;   // 0:success 1: 除0 2: 非法操作 3. 4. 5};//创建需求class Factory{public:Factory(){srand(time(nullptr) ^ getpid());opers = "+-*/%^&|";                                                                                                                 }std::shared_ptr<Request> BuildRequest(){int x = rand() % 10 + 1;usleep(x * 10);int y = rand() % 5; // [0,1,2,3,4]usleep(y * x * 5);char oper = opers[rand() % opers.size()];std::shared_ptr<Request> req= std::make_shared<Request>(x,y,oper);return req;}std::shared_ptr<Response> BuildResponse(){return std::make_shared<Response>();}~Factory(){}private:std::string opers;};
}

在这里插入图片描述

CalCulate.hpp

将已经反序列化的数据通过计算得出结果:

#pragma once
#include <iostream>
#include "ProToCol.hpp"using namespace protocol_ns;class Calculate
{
public:Calculate(){}//根据输入的请求通过实际计算转换为结果Response Excute(const Request &req){Response resp(0, 0);switch (req._oper){case '+':resp._result = req._x + req._y;break;case '-':resp._result = req._x - req._y;break;case '*':resp._result = req._x * req._y;break;case '/':{if (req._y == 0){resp._code = 1;}else{resp._result = req._x / req._y;}}break;case '%':{if (req._y == 0){resp._code = 2;}else{resp._result = req._x % req._y;}}break;default:resp._code = 3;break;}return resp;}~Calculate(){}private:
};

在这里插入图片描述

TcpServerMain.cc

#include <iostream>
#include <functional>
#include <memory>
#include "TcpServer.hpp"
#include "ProToCol.hpp"
#include"CalCulate.hpp"
using namespace protocol_ns;using callback_t = std::function<Response(const Request&)>;//响应计算结果的函数指针
void Usage(std::string proc)
{std::cout << "Usage:\n\t" << proc << " local_port\n"<< std::endl;
}//由于接收的是报文,需要通过反序列化和序列化反复转换并且期间要完成计算的服务
class Service
{
public:Service(callback_t cb) : _cb(cb){}//套接字指针:客户端的sockfd   网络地址:客户端void ServiceHelper(socket_sptr sockptr,InetAddr client){int sockfd = sockptr->SockFd();LOG(DEBUG, "get a new link, info %s:%d, fd : %d\n",client.Ip().c_str(),client.Port(),sockfd );std::string clientaddr = "[" + client.Ip() + ":" + std::to_string(client.Port()) + "] ";std::string inbuffer;while(true){sleep(5);Request req;// 1.接收来自客户端的发送数据,接收时是已被序列化的数据信息int n = sockptr->Recv(&inbuffer); if (n < 0){LOG(DEBUG, "client %s quit\n", clientaddr.c_str());break;}std::string package;while (true)//传递途中可能会出现数据丢失,要通过循环直到找到有效正确的数据信息{//2.分析报文中的有效数据sleep(1);std::cout << "inbuffer: " << inbuffer << std::endl;package = Decode(inbuffer);//解析报文if (package.empty())break;std::cout << "------------------------begin---------------" << std::endl;std::cout << "resq string:\n"<< package << std::endl;  // 3.反序列化,将字符串变为结构体信息req.DeSerialize(package);// 4. 业务处理Response resp = _cb(req);// 5. 对应答做序列化std::string send_str;resp.Serialize(&send_str);std::cout << "resp Serialize:" << std::endl;std::cout << send_str << std::endl; // 6. 添加长度报头send_str = Encode(send_str);std::cout << "resp Encode:" << std::endl;std::cout << send_str << std::endl;// "len"\r\n"{             }"\r\n"sockptr->Send(send_str); // 本次不对发送做处理, EPOLL     }}}
private:callback_t _cb; //将需求转换为结果
};// ./tcpserver port
int main(int argc, char *argv[])
{if (argc != 2){Usage(argv[0]);return 1;}uint16_t port = std::stoi(argv[1]);Calculate cal;Service calservice(std::bind(&Calculate::Excute, &cal, std::placeholders::_1));//通过Service解决报文问题io_service_t service = std::bind(&Service::ServiceHelper, &calservice, std::placeholders::_1, std::placeholders::_2);//将服务和服务器耦合std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(port, service);tsvr->Loop();return 0;
}

在这里插入图片描述

TcpClientMain.cc

#include <iostream>
#include <string>
#include <memory>
#include <ctime>
#include "Socket.hpp"
#include "ProToCol.hpp"
#include "InetAddr.hpp"using namespace socket_ns;
using namespace protocol_ns;void Usage(std::string proc)
{std::cout << "Usage:\n\t" << proc << " serverip serverport\n"<< std::endl;           
}int main(int argc,char* argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}std::string serverip = argv[1];//服务端ipuint16_t serverport = std::stoi(argv[2]);//服务端端口号InetAddr serveraddr(serverip, serverport);//创建网络地址Factory factory;//std::shared_ptr<Socket> cli=std::make_shared<TcpSocket>();//创建套接字的智能指针bool res=cli->BuildClientSocket(serveraddr); //创建Client套接字并连接到服务端std::string inbuffer; //接收应答时存储对方的数据while (res){sleep(1);std::string str;//一次创建5个请求出来//for(int i=0;i<5;i++)//{// 1. 构建一个请求auto req = factory.BuildRequest();// 2. 对请求进行序列化std::string send_str; //序列化后保存于此req->Serialize(&send_str);std::cout << "Serialize: \n"<< send_str << std::endl;// 3. 添加长度报头send_str = Encode(send_str);std::cout << "Encode: \n"<< send_str << std::endl;str += send_str;//}//4.发送报文cli->Send(str);// 5. 读取应答int n = cli->Recv(&inbuffer);//接收应答if (n <= 0)break;std::string package = Decode(inbuffer); //解析报文if (package.empty()) //一旦为空那么继续解析下一个报文continue;// 6. 反序列化auto resp = factory.BuildResponse();resp->Deserialize(package);std::cout<<"result: "<<resp->_result<<"["<< resp->_code <<"]"<<std::endl;}
}

结果

在这里插入图片描述
在这里插入图片描述

相关文章:

Linux--序列化与反序列化

序列化 序列化是指将数据结构或对象状态转换成可以存储或传输的格式的过程。在序列化过程中&#xff0c;对象的状态信息被转换为可以保持或传输的格式&#xff08;如二进制、XML、JSON等&#xff09;。序列化后的数据可以被写入到文件、数据库、内存缓冲区中&#xff0c;或者通…...

使用C#和 aspose.total 实现替换pdf中的文字(外语:捷克语言的pdf),并生成新的pdf导出到指定路径

程序主入口&#xff1a; Program.cs &#xfeff;using System; using System.Collections.Generic; using System.Configuration; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks;namespace PdfEditor {public class Progra…...

【Material-UI】Autocomplete中的高亮功能(Highlights)详解

文章目录 一、简介二、实现高亮功能示例代码代码解释 三、实际应用场景1. 搜索功能2. 表单自动完成 四、总结 在现代Web开发中&#xff0c;提供清晰的用户反馈是提升用户体验的重要组成部分。Material-UI的Autocomplete组件通过高亮功能&#xff0c;帮助用户快速识别搜索结果中…...

Android 11(R)启动流程 初版

启动流程 bootloader会去启动android第一个进程Idle&#xff0c;pid为0&#xff0c;会对进程 内存管理等进行初始化。Idle还被称作swapper。Idle会去创建两个进程&#xff0c;一个是init&#xff0c;另外一个是kthread。 kthread会去启动内核&#xff0c;用户是由init进行启动。…...

从零安装pytorch

背景介绍 目前主流使用的工具有Facebook搞的pythorch和谷歌开发的tensorflow两种&#xff0c;二者在实现理念上有一定区别&#xff0c;pytorch和人的思维模式与变成习惯更像&#xff0c;而tensorflow则是先构建整体结构&#xff0c;然后整体运行&#xff0c;开发调试过程较为繁…...

2024.07.28 校招 实习 内推 面经

绿*泡*泡VX&#xff1a; neituijunsir 交流*裙 &#xff0c;内推/实习/校招汇总表格 1、自动驾驶一周资讯 - 特斯拉FSD年底入华&#xff1f;理想成立“端到端”实体组织&#xff1b;小马智行或最快于今年9月赴美IPO 自动驾驶一周资讯 - 特斯拉FSD年底入华&#xff1f;理想…...

python实现小游戏——植物大战僵尸(魔改版本)

制作一款DIY的‘植物大战僵尸’游戏引起了很多人的兴趣。在这里&#xff0c;我将分享一个使用Python语言在PyCharm环境中开发的初始状态版本。这个版本主要应用了pygame库来完成&#xff0c;是一个充满创意和趣味的魔改版本。 文章目录 前言一、开发环境准备二、代码1.main方法…...

基于K210智能人脸识别+车牌识别系统(完整工程资料源码)

运行效果&#xff1a; 基于K210的智能人脸与车牌识别系统工程 目录&#xff1a; 运行效果&#xff1a; 目录&#xff1a; 前言&#xff1a; 一、国内外研究现状与发展趋势 二、相关技术基础 2.1 人脸识别技术 2.2 车牌识别技术 三、智能小区门禁系统设计 3.1 系统设计方案 3.2 …...

8.怎么配嵌套子路由,以及它的作用

作用 配嵌套子路由,就是可以通过同一个页面,让不同的位置发生变化,其他的位置不会发生变化,而做到一个局部刷新 例子 红线框住的部分,头部和导航栏是不会发生变化的,变化的只有中间的内容 子路由的操作步骤 将这个页面的头部和导航栏部分的样式和风格,移到主路由上(<tem…...

【海贼王航海日志:前端技术探索】HTML你学会了吗?(二)

目录 1 -> HTML常见标签 1.1 -> 表格标签 1.1.1 -> 基本使用 1.1.2 -> 合并单元格 1.2 -> 列表标签 1.3 -> 表单标签 1.3.1 -> form标签 1.3.2 -> input标签 1.4 -> label标签 1.5 -> select标签 1.6 -> textarea标签 1.7 -> …...

体系结构论文导读(三十一)(下):Soft errors in DNN accelerators: A comprehensive review

第五部分&#xff1a;DNN加速器中的软错误 本部分回顾和分析了有关人工神经网络&#xff08;ANN&#xff09;可靠性的研究。特别是关注通过DNN加速器解决DNN可靠性的研究&#xff0c;从软错误的角度进行探讨。许多前期工作声称ANN本身对故障具有固有的容错能力。然而&#xff…...

Python在指定文件夹下创建虚拟环境

基于不同python版本和第三方包版本开发的项目&#xff0c;为了方便学习和管理python环境&#xff0c;可以在指定的文件夹里创建项目所需的虚拟环境。具体流程如下&#xff1a; (1) 以管理员身份打开Ananconda Prompt&#xff0c;查看当前虚拟环境&#xff0c;输入命令如下&…...

【SpringBoot】 定时任务之任务执行和调度及使用指南

【SpringBoot】 定时任务之任务执行和调度及使用指南 Spring框架分别通过TaskExecutor和TaskScheduler接口为任务的异步执行和调度提供了抽象。Spring还提供了支持应用程序服务器环境中的线程池或CommonJ委托的那些接口的实现。最终&#xff0c;在公共接口后面使用这些实现&…...

理解 Objective-C 中 +load 方法的执行顺序

在 Objective-C 中&#xff0c;load 方法是在类或分类&#xff08;category&#xff09;被加载到内存时调用的。它的执行顺序非常严格&#xff0c;并且在应用启动过程中可能会导致一些令人困惑的行为。理解 load 方法的执行顺序对调试和控制应用的初始化过程非常重要。 load 方…...

切面条问题算法的详解

切面条问题是一个经典的动态规划问题&#xff0c;也称为切钢条问题。问题描述为&#xff1a;给定一根长度为n的钢条和一个价格表P[i]&#xff0c;表示长度为i的钢条的价格。求解如何切割钢条使得收益最大。 解决这个问题的关键是找到一个最优子结构和递推关系。 首先&#xf…...

JNDI注入

&#x1f3bc;个人主页&#xff1a;金灰 &#x1f60e;作者简介:一名简单的大一学生;易编橙终身成长社群的嘉宾.✨ 专注网络空间安全服务,期待与您的交流分享~ 感谢您的点赞、关注、评论、收藏、是对我最大的认可和支持&#xff01;❤️ &#x1f34a;易编橙终身成长社群&#…...

SQL Server数据库文件过大而无法直接导出解决方案

目录 1. 使用分割备份 (Split Backup) 2. 使用文件和文件组备份 (File and Filegroup Backup) 3. 使用压缩备份 (Compressed Backup) 4. 逻辑备份 (BCP工具) 5. 使用导出工具 (SQL Server Management Studio) 6. 部分备份 (Partial Backup) 7. 使用第三方工具 1. 使用分割…...

学习日志8.4--DHCP攻击防范

目录 DHCP饿死攻击 DHCP Sever仿冒攻击 DHCP攻击防范 DHCP动态主机配置协议&#xff0c;是给主机提供自动获取IP地址等配置信息的服务。在主机对DHCP服务器发送DHCP Discover请求之后&#xff0c;服务器回复offer&#xff0c;主机再回复request&#xff0c;最后服务器回复AC…...

解决多个Jenkins Master实例共享Jenkins_home目录的问题(加锁解锁机制)

在Jenkins的持续集成和持续部署&#xff08;CI/CD&#xff09;环境中&#xff0c;JENKINS_HOME目录扮演着至关重要的角色。它存储了Jenkins的配置、插件、作业历史记录等核心数据。然而&#xff0c;在某些场景下&#xff0c;我们可能面临多个Jenkins master实例需要共享同一个J…...

postgresql array 反向截取

postgresql array 反向截取 array_to_string((string_to_array(REPLACE(delcell.小区网管名称,‘‘,’-‘),’-‘))[:array_length(string_to_array(REPLACE(delcell.小区网管名称,’’,‘-’),‘-’),1)-1],‘-’) as 基站名称 在PostgreSQL中&#xff0c;如果你想要对数组进…...

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周&#xff0c;有很多同学在写期末Java web作业时&#xff0c;运行tomcat出现乱码问题&#xff0c;经过多次解决与研究&#xff0c;我做了如下整理&#xff1a; 原因&#xff1a; IDEA本身编码与tomcat的编码与Windows编码不同导致&#xff0c;Windows 系统控制台…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...