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

齐齐哈尔市建设工程监察网站ppt模板下载网址

齐齐哈尔市建设工程监察网站,ppt模板下载网址,wordpress爱找主题,媒体平台是什么【Linux网络编程七】网络序列化和反序列化(网络版本计算器#xff09; 一.网络读取问题【解决方案】1.定制协议2.序列化和反序列化3.添加报头①封包②解包 4.框架总结 二.自定义协议#xff1a;网络计算器协议Ⅰ.客户端发送请求#xff0c;服务器端接收请求1.构建请求(结构化… 【Linux网络编程七】网络序列化和反序列化(网络版本计算器 一.网络读取问题【解决方案】1.定制协议2.序列化和反序列化3.添加报头①封包②解包 4.框架总结 二.自定义协议网络计算器协议Ⅰ.客户端发送请求服务器端接收请求1.构建请求(结构化数据)2.请求序列化3.添加报头发送到网络4.服务器读取请求5.解除报头6.请求反序列化 Ⅱ.服务器端发送响应客户端接收响应1.构建响应(结构化数据)2.响应序列化3.添加报头发送到网络4.客户端读取响应5.解除报头6.响应反序列化 三.自动序列化和反序列化Json四.理解OSI七层协议 一.网络读取问题 在网络通信时通信双方是无法保证读取时能够正确的读取到想要的内容的。 这是什么意思呢 【解决方案】 1.定制协议 什么叫定制协议呢就是让双方都要能知道约定好的一些字段然后以结构化的形式发送和接收。 定制的协议双方都要能认识才可以通信。不然一方认识另一方不认识就无法通信了。 2.序列化和反序列化 定制好结构体后然后构建一个对象是不是就可以直接发送过去了呢 当然不可以为什么呢 1.我们不能直接将结构体对象直接发送给对端机器因为双方可能机器不同对于结构体的解读会不一样最终就会解析错误。所以通常我们不直接发送结构化数据到网络里而是发送字符串形式的数据给对端。 2.也就是我们需要在构建完结构化数据后在发送到网络里之前还需要将它转换成字符串形式才能发送。这个过程就叫做序列化 3.而对端机器从网络里接收到字符串后它并不认识这个字符串是什么意思只有将这个字符串转成结构化化数据它才能知道对方发送的是什么信息。而将字符串数据再转成结构化数据就叫做反序列化。 3.添加报头 那么问题又回来了对端是如何正确获取到想要的完整报文的呢 我们可以利用一些特殊字符来区别报文与报文。而如果想要对方准确的接收到一个完整的报文那么就可以通过在报文前面添加一个长度单位标识这个报文总长度有多少一旦对端读取到这个长度就可以直接从后面截取报文的长度就可以直接完整的获取到一个报文。 而在报文前面添加一个长度单位这个行为我们可以称为添加一个报头。 添加报头的目的就是为了让对端在读取的时候能够根据报头来完整的获取一个报文。所以添加报头也是属于定制协议的部分。通信的双方都要能识别。 ①封包 所以构建完结构化数据后在发送到网络之前需要将之转换成字符串形式也就是序列化。然后为了让对端能够准确的获取到一个完整的报文我们还需要对这个字符串添加报头。 ②解包 对端获取到从网络里发送来的数据后并不理解是什么意思所以需要反序列化将字符串数据转换成结构化数据这样它就可以理解是什么意思了。 但是这里存在的问题就是它并不能确定对方发送的是一个报文还是多个报文还是半个报文。因为从网络里发送来的就是一个字符串形式的数据。它分析不出来。而反序列化是以一个完整的报文进行反序列化的因为当时序列化的时候就是一个完整的结构体数据进行序列化的。 所以定制协议的人考虑到这点就在报文的前面添加了一个报头表明报文的长度的字段。这样只要对端接收到报文然后依据报头就能分析出对方发送的数据是否是完整的了。如果是完整的那么直接获取有效的报文。如果不是完整的那么重新去读取如果是多个报文那么我们只要一个完整的报文即可。剩下的等下次再处理。 4.框架总结 网络部分套接字 Socket.hpp #pragma once //将网络套接字编程部分直接封装打包因为服务器和客户端都需要使用创建套接字等操作。 #include iostream #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include Log.hpp #include cstdlib #include cstring #include unistd.h enum {SocketErr1,BindErr,ListenErr, }; const int backlog10; class Sock {public:Sock(){}~Sock(){}void Socket()//创建套接字{_socketsocket(AF_INET,SOCK_STREAM,0);if(_socket0){lg(Fatal,socket err:%s :%d,strerror(errno),errno);exit(SocketErr);}}void Bind(uint16_t port)//绑定套接字{struct sockaddr_in local;memset(local,0,sizeof(local));local.sin_addr.s_addrINADDR_ANY;//将ip地址初始化成0local.sin_familyAF_INET;local.sin_porthtons(port);if(bind(_socket,(struct sockaddr*)local,sizeof(local))0){lg(Fatal,bind err :%s :%d,strerror(errno),errno);exit(BindErr);}}void Listen()//将套接字设置成监听状态{if(listen(_socket,backlog)0){lg(Fatal,listen err :%s :%d,strerror(errno),errno);exit(ListenErr);}}int Accept(std::string *clientip,std::uint16_t* clientport)//服务器获取连接并获取对方的网络信息,将获取的到的新连接交给服务函数操作{struct sockaddr_in client;socklen_t lensizeof(client);int newsockaccept(_socket,(struct sockaddr*)client,len);if(newsock0){lg(Warning,accept err :%s :%d,strerror(errno),errno);return -1;}*clientportntohs(client.sin_port);char Clientip[32];inet_ntop(AF_INET,client.sin_addr,Clientip,sizeof(Clientip));*clientipClientip;return newsock;}bool Connect(const std::string serverip,const uint16_t serverport)//需要知道要连接的对方的网络信息{struct sockaddr_in local;socklen_t lensizeof(local);memset(local,0,sizeof(local));local.sin_familyAF_INET;local.sin_porthtons(serverport);inet_pton(AF_INET,serverip.c_str(),local.sin_addr);int nconnect(_socket,(struct sockaddr*)local,len);if(n-1){std::cerrconnect toserverip:serverporterrorstd::endl;return false;}return true;}void Close(){close(_socket);}int Fd(){return _socket;} private: int _socket; };协议部分 Protocol.hpp #pragma once //#define MySelf 1 // 在网络通信之前我们服务器端和客户端都需要知道协议。我们也可以自己定制协议这个协议要被双方都能识别 // 比如我们可以定制一个计数器协议。协议就是一种约定除了数据本身还有其他的字段。 // 1.我们要求将数据以结构化的形式保存这样双方都可以识别这个结构体对象但传入网络里时需要转换成字符类型。这个过程就是序列化.序列化的过程就是在构建有效载荷 // 2.对方接收到字符串类型的数据时想要用服务操作时发现是不能操作的是因为它不认识这时还需要将字符类型转成结构体类型这个过程叫做反序列化。 // 3.为了能让对方接收时能接收读取到对方想要的完整报文时我们采取添加报头的形式来解决。 // 4.所以在将报文传入到网络里时还需要添加报文当对端接收到报文时想要对它进行处理之前还需要将报文的报头解包才可以正确处理。 #include iostream #include jsoncpp/json/json.h #include string const std::string blank_space ; const std::string protocol_space\n; // 封包报文在发送到网络之前需要添加一些报头来达到一些要求 std::string Encode(const std::string content)//content就是有效载荷 {//x y------len\nx y\n 添加了一个报文长度和两个\nstd::string packpagestd::to_string(content.size());packpageprotocol_space;packpagecontent;packpageprotocol_space;return packpage; }// 解包对端读取到报文(可能读取到的不是想要的根据原先添加上去的报头来获取准确想要的报文)想要处理它需要先解除报头才能处理 bool Decode(std::string packpage, std::string *content) { //len\nx y\n----x ystd::size_t pospackpage.find(protocol_space);if(posstd::string::npos)return false;std::string len_strpackpage.substr(0,pos);//判断一下是否读取的内容是全部的std::size_t len std::stoi(len_str);std::size_t total_lenlen_str.size()len2;if(packpage.size()total_len)//说明不是一个完整的报文return false;*contentpackpage.substr(pos1,len);//为了真正的拿走报文还需要将响应inbuffer里的报文移除erase这样才是真正的拿走报文packpage.erase(0,total_len);return true; }class Request { public:Request(){}Request(int data1, int data2, char op) : _x(data1), _y(data2), _op(op) // 最初形成结构化数据{}bool Serialize(std::string *out) // 序列化单纯的就是将结构体转换成字符串{ #ifdef MySelf // 构建报文的有效载荷// struct》x ystd::string s std::to_string(_x);s blank_space;s _op;s blank_space;s std::to_string(_y);*out s;return true;#elseJson::Value root;//定义一个万能对象可以存储数据k-v形式的结构体root[x]_x;root[y]_y;root[op]_op;//Json::FastWriter w;Json::StyledWriter w;*outw.write(root);//序列化成字符串return true; #endif}bool Deserialize(std::string in) // 反序列化就单纯的将字符串类型转成结构体{ #ifdef MySelf //x ystruct//获取左操作数xstd::size_t leftin.find(blank_space);if(leftstd::string::npos)return false;std::string part_xin.substr(0,left);//获取右操作数ystd::size_t rightin.rfind(blank_space);if(rightstd::string::npos)return false;std::string part_yin.substr(right1);//获取操作码opif(left2!right)return false;_opin[left1];_xstd::stoi(part_x);_ystd::stoi(part_y);return true; #elseJson::Value root;//定义一个万能对象将序列化的数据存储在里面Json::Reader r;r.parse(in,root);//将数据存到万能对象里后我们就可以根据key值找到_xroot[x].asInt();_yroot[y].asInt();_oproot[op].asInt();return true; #endif }void DebugPrint(){std::cout新请求构建完毕_x_op_y???std::endl;} public: // x yint _x;int _y;char _op; }; class Response { public:Response(int reslut, int code) : _reslut(reslut), _code(code){}Response(){}bool Serialize(std::string *out) // 序列化单纯的就是将结构体转换成字符串{ #ifdef MySelf//reslut code//构建报文的有效载荷std::string sstd::to_string(_reslut);sblank_space;sstd::to_string(_code);*outs;return true; #elseJson::Value root;root[reslut]_reslut;root[code]_code;//Json::FastWriter w;Json::StyledWriter w;*outw.write(root);return true; #endif }bool Deserialize(std::string in){ #ifdef MySelf//reslut code--结构体类型std::size_t posin.find(blank_space);if(posstd::string::npos)return false;std::string part_leftin.substr(0,pos);std::string part_rightin.substr(pos1);_reslutstd::stoi(part_left);_codestd::stoi(part_right);return true; #elseJson::Value root;Json::Reader r;r.parse(in,root);//将字符串数据存到万能对象里_reslutroot[reslut].asInt();_coderoot[code].asInt();return true; #endif}void DebugPrint(){std::cout结果响应完成,reslut: _reslut,code: _codestd::endl;}public:int _reslut;int _code; }; 服务器服务部分 ServerCal.hpp #pragma once #include Protocol.hpp #include iostream #include string // 服务器端从网络里读取到数据后就要进行处理服务。 // 1.首先需要对报文进行解包2.解包后还需要将报文转成结构体类型对方才能识别 enum {Div_Zero 1,Mod_Zero,Other_Oper } ; class ServerCal { public:Response Calculatorhelpor(const Request req){Response resp(0, 0);switch (req._op){case :resp._reslut req._x req._y;break;case -:resp._reslut req._x - req._y;break;case *:resp._reslut req._x * req._y;break;case /:{if (req._y 0)resp._code Div_Zero;elseresp._reslut req._x / req._y;}break;case %:{if (req._y 0)resp._code Mod_Zero;elseresp._reslut req._x % req._y;}break;default:resp._codeOther_Oper;break;}return resp;}std::string Calculator(std::string package){std::string content; //len\n20 10\nbool r Decode(package, content); //20 10if (!r)return ;Request req; // 反序列化r req.Deserialize(content);if (!r)return ;// 服务器端解包获取到报文后就可以进行计算再将计算结果返回回到网络里,网络里需要序列化的数据Response res Calculatorhelpor(req); // reslut30 code0content ;res.Serialize(content); //30 0content Encode(content); //len\n30 0\nreturn content;} };二.自定义协议网络计算器协议 Ⅰ.客户端发送请求服务器端接收请求 ClientCal.cc #include iostream #include time.h #include unistd.h #include assert.h #include Socket.hpp #include Protocol.hpp void Usage(std::string proc) {std::cout\n\rUsage: proc port[1024]\nstd::endl; } //./tcpclient ip port int main(int args,char* argv[]) {if(args!3){Usage(argv[0]);exit(1);}std::string serveripargv[1];uint16_t serverportstd::stoi(argv[2]);Sock sockfd;sockfd.Socket();//创建套接字bool rsockfd.Connect(serverip,serverport);//发起连接if(!r)return 1;srand(time(nullptr)^getpid());int cnt1;std::string oper-*/%$;std::string inbuffer_stream;while(cnt10){std::cout第cnt次测试std::endl;//1.开始构建请求int xrand()%1001;usleep(1234);int yrand()%100;usleep(4321);char opoper[rand()%oper.size()];Request req(x,y,op);//2.请求构建完毕req.DebugPrint();//3.数据序列化形成报文std::string content;req.Serialize(content);//4.添加报头std::string packpageEncode(content);//5.发送到网络里write(sockfd.Fd(),packpage.c_str(),packpage.size());//6.接收服务器端发送来的响应char buffer[128];ssize_t nread(sockfd.Fd(),buffer,sizeof(buffer));//6.1处理读取if(n0){buffer[n]0;inbuffer_streambuffer;//接收到的是一个协议报文len\nreslut code\nstd::coutstd::endl;std::cout获取到的网络答应std::endl;std::coutinbuffer_streamstd::endl;//将从网络里获取到的报文打印出来//7.首先需要解包检测std::string content;bool r Decode(inbuffer_stream,content);assert(r);//8.反序列化将答应变成客户端可认识的形式Response resp;rresp.Deserialize(content);assert(r);//9.结果响应完成resp.DebugPrint();}std::coutstd::endl;sleep(1);cnt;}sockfd.Close(); } 1.构建请求(结构化数据) 2.请求序列化 3.添加报头发送到网络 4.服务器读取请求 5.解除报头 6.请求反序列化 Ⅱ.服务器端发送响应客户端接收响应 Main.cc #include Tcpserver.hpp #include ServerCal.hpp #include memory void Usage(std::string proc) {std::cout \n\rUsage: proc port[1024]\n std::endl; }int main(int args, char *argv[]) {if (args ! 2){Usage(argv[0]);exit(0);}uint16_t port std::stoi(argv[1]);ServerCal cal;Tcpserver *tcpsvr new Tcpserver(port, std::bind(ServerCal::Calculator, cal, std::placeholders::_1));tcpsvr-Init();tcpsvr-Start();return 0; }Tcpserver.hpp #pragma once #include iostream #include string #include functional #include Log.hpp #include signal.h #include Socket.hpp #include ServerCal.hpp Sock sock; using func_t std::functionstd::string(std::string package);class Tcpserver {public:Tcpserver(uint16_t port,func_t callback) : _port(port),_callback(callback){}bool Init(){_listensock.Socket(); // 创建套接字_listensock.Bind(_port); // 绑定套接字_listensock.Listen(); // 将套接字设置成监听状态lg(Info, init server...done);return true;}void Start() // 启动服务器{ // 启动之前需要先忽略一些信号signal(SIGPIPE, SIG_IGN);signal(SIGCHLD, SIG_IGN);// 获取连接while (true){std::string clientip;uint16_t clientport;int sockfd _listensock.Accept(clientip, clientport);if (sockfd 0)continue;lg(Info, accept a new link, sockfd:%d, clientip%s ,clientport: %d,sockfd,clientip.c_str(),clientport);// 提供服务--让子进程提供服务if (fork() 0){_listensock.Close();std::string inbuffer_stream;while (true){// 1.读取网络中的数据流char buffer[128];size_t n read(sockfd, buffer, sizeof(buffer));if (n 0){buffer[n]0;//将读取的报文进行处理inbuffer_streambuffer;//注意读取的内容必须是一个完整的内容不然调用回调时就回调用失败lg(Debug,获取的网络请求:\n %s,inbuffer_stream.c_str());std::string info_callback(inbuffer_stream);if(info.empty())continue;//如果进行计算时发现报文有问题就重新回来读取。// 2.将处理的结果发送回网络中write(sockfd,info.c_str(),info.size());}else if(n0)break;else break;}exit(0);}close(sockfd);}}~Tcpserver(){}private:uint16_t _port;Sock _listensock;func_t _callback; };1.构建响应(结构化数据) 2.响应序列化 3.添加报头发送到网络 4.客户端读取响应 5.解除报头 6.响应反序列化 三.自动序列化和反序列化Json bool Serialize(std::string *out) // 序列化单纯的就是将结构体转换成字符串{Json::Value root;//定义一个万能对象可以存储数据k-v形式的结构体root[x]_x;root[y]_y;root[op]_op;//Json::FastWriter w;Json::StyledWriter w;*outw.write(root);//序列化成字符串return true; }bool Deserialize(std::string in) // 反序列化就单纯的将字符串类型转成结构体{Json::Value root;//定义一个万能对象将序列化的数据存储在里面Json::Reader r;r.parse(in,root);//将数据存到万能对象里后我们就可以根据key值找到_xroot[x].asInt();_yroot[y].asInt();_oproot[op].asInt();return true;}四.理解OSI七层协议
http://www.w-s-a.com/news/418580/

相关文章:

  • vs 团队网站开发中铁建设门户网登录咋进不去了
  • 快速网站建设公司哪家好优秀的网站建设
  • 网站开发的自适应wordpress搜索词结果按文章标题
  • 微网站是用什么开发的wordpress中英文主题
  • 纯静态网站怎么做淄博seo开发
  • 江西新农村建设权威网站盐步网站制作
  • 网站ui设计例子怎么做打鱼网站
  • 在1688做公司网站wordpress category
  • 单页面 网站 模板网站代理公司
  • 手机网站底部电话代码网站后台点击添加图片没有反应
  • 龙岩建设局网站声明自学制作网站难不难
  • 济南网站优化小黑godaddy中文网站开发
  • 做微课常用的网站广州seo优化推广
  • 主机屋如何做网站电脑网页游戏大全
  • 工作网站建设中布线费用账务处理特色的重庆网站推广
  • dede 网站地图模板htm写作网站水平哪个最好
  • 服务器上的网站erp教学零基础入门
  • 网站建设58设计资料网站
  • 如何把动态图发网站做头像网页设计实训报告小结
  • 做简历用的网站wordpress版权说明
  • 网站关键词有哪些网站新闻前置审批
  • 怎么自己注册网站义乌做公司网站
  • 做哪种网站赚钱苏州住房城乡建设部网站
  • 镇江做网站学编程学哪一种比较好
  • 华美天一建筑公司网站赚钱做任务的网站有哪些
  • asp网站打开速度慢家乡网页设计教程
  • 网站 设计 深圳书店网站的建设
  • 北京网络营销推广培训哪家好南宁软件优化网站建设
  • flash网站引导页仓库管理系统源码
  • 济南网站制作公司排名营销型网站管理系统