品牌创意型网站开发,程序ui设计,全球军情动态,做一个响应网站多少钱序列化
序列化是指将数据结构或对象状态转换成可以存储或传输的格式的过程。在序列化过程中#xff0c;对象的状态信息被转换为可以保持或传输的格式#xff08;如二进制、XML、JSON等#xff09;。序列化后的数据可以被写入到文件、数据库、内存缓冲区中#xff0c;或者通…序列化
序列化是指将数据结构或对象状态转换成可以存储或传输的格式的过程。在序列化过程中对象的状态信息被转换为可以保持或传输的格式如二进制、XML、JSON等。序列化后的数据可以被写入到文件、数据库、内存缓冲区中或者通过网络发送到另一个系统。
序列化的主要目的包括
持久化将对象状态保存到存储系统中以便程序在重新启动时能够重新加载这些数据。网络传输在分布式系统中对象需要通过网络发送到其他节点序列化是实现这一点的关键步骤。数据交换不同的应用程序或系统之间可能需要交换数据序列化提供了一种标准化的数据格式。
反序列化
反序列化是序列化的逆过程即将序列化后的数据如二进制、XML、JSON等恢复成原始的数据结构或对象状态。在反序列化过程中原始的数据格式被解析并重新构建成原始对象或数据结构。
反序列化的主要目的是
恢复对象状态从存储系统或网络接收的数据中恢复对象的状态。数据使用在应用程序中使用反序列化后的数据。
JSON
JSONJavaScript 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.hppnamespace socket_ns
{class Socket;const static int gbacklog8;//默认最大连接数using socket_sptrstd::shared_ptrSocket;//套接字指针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明确的重写基类函数{_sockfdsocket(AF_INET,SOCK_STREAM,0);if(_sockfd0){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 nbind(_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 nlisten(_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 lensizeof(peer);int sockfd accept(_sockfd,(struct sockaddr*)peer,len);if (sockfd 0){LOG(WARNING, accept error\n);return nullptr;}*addrpeer;socket_sptr sockstd::make_sharedTcpSocket(sockfd);return sock;}virtual bool Connector(InetAddr addr){struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_familyAF_INET;server.sin_addr.s_addrinet_addr(addr.Ip().c_str());server.sin_porthtons(addr.Port());int nconnect(_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
#includeunistd.h
#includememory
#includejsoncpp/json/json.hnamespace 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;*outwriter.write(root); //将Json值转换为字符串return true;}//反序列化将字符串转换为结构体数据bool DeSerialize(const std::string in){Json::Value root;Json::Reader reader;//解析字符串bool resreader.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_ptrRequest 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_ptrRequest req std::make_sharedRequest(x,y,oper);return req;}std::shared_ptrResponse BuildResponse(){return std::make_sharedResponse();}~Factory(){}private:std::string opers;};
}CalCulate.hpp
将已经反序列化的数据通过计算得出结果
#pragma once
#include iostream
#include ProToCol.hppusing 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
#includeCalCulate.hpp
using namespace protocol_ns;using callback_t std::functionResponse(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\nsockptr-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_ptrTcpServer tsvr std::make_uniqueTcpServer(port, service);tsvr-Loop();return 0;
}TcpClientMain.cc
#include iostream
#include string
#include memory
#include ctime
#include Socket.hpp
#include ProToCol.hpp
#include InetAddr.hppusing 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_ptrSocket clistd::make_sharedTcpSocket();//创建套接字的智能指针bool rescli-BuildClientSocket(serveraddr); //创建Client套接字并连接到服务端std::string inbuffer; //接收应答时存储对方的数据while (res){sleep(1);std::string str;//一次创建5个请求出来//for(int i0;i5;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::coutresult: resp-_result[ resp-_code ]std::endl;}
}结果