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

手机网站制作步骤网站设计的市场分析

手机网站制作步骤,网站设计的市场分析,建设地方美食网站的目的,网络工程师官网目录 序列化和反序列化 上期我们学习了基于TCP的socket套接字编程接口,并实现了一个TCP网络小程序,本期我们将在此基础上进一步延伸学习,实现一个网络版简单计算器。 序列化和反序列化 在生活中肯定有这样一个情景。 上图大家肯定不陌生&a…

目录

序列化和反序列化


上期我们学习了基于TCP的socket套接字编程接口,并实现了一个TCP网络小程序,本期我们将在此基础上进一步延伸学习,实现一个网络版简单计算器。

序列化和反序列化

在生活中肯定有这样一个情景。

上图大家肯定不陌生,上图是群聊机器人发送的一条消息记录,通过这个记录我们可以看到机器人的头像,机器人的昵称,机器人发送的消息内容,机器人发送消息的时间。我上述数据统称为一次发送产生的数据。使用qq的人是很多的,所以上述数据也是很多,为了方便进行管理数据,操作系统会将一次发送的数据进行管理,这就要用到六子真言,“先描述,后组织”。所以操作系统会定义一个结构体,结构体中会定义一些成员表述上述的数据,我们称之为结构化数据。

 图示如下。

总的来说。

序列化就是将结构化的数据转为字符串数据,反序列化就是将字符串数据转为结构化数据。

序列化和反序列化的优点。

  1. 为了应用层网络通信的便捷,因为在网络通信中,字符串更易于传输。
  2.  为了方便上层端口使用结构化数据内部的成员,将应用和网络进行了解耦。比如发送端发送什么类型的数据,接收端就接收什么类型的数据,双方都不用关心结构化数据在网络中是怎么样传送的。

情景一:制造一个网络计算器小程序(不使用序列化和反序列化)。

Sock.hpp

#include <iostream>
#include <sys/types.h>
#include <cerrno>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>using namespace std;class Socket
{
public:// 1.创建套接字static int Sock(){int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd < 0){cout << "socket create error" << errno << endl;exit(1);}return fd;}// 2.绑定IP和端口号static void Bind(int sock, uint16_t port){struct sockaddr_in local;local.sin_family = AF_INET;local.sin_port = htons(port);local.sin_addr.s_addr = INADDR_ANY;if (bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0){cout << "bind error" << errno << endl;exit(2);}}// 3.监听连接static void Listen(int sock){if (listen(sock, 5) < 0){cout << "listen error" << errno << endl;exit(3);}}// 4.获取连接static int Accept(int sock){struct sockaddr_in peer;socklen_t len = sizeof(peer);int newfd = accept(sock, (struct sockaddr *)&peer, &len);if (newfd < 0){cout << "accept error" << errno << endl;exit(4);}return newfd;}// 5.发送链接static void Connect(int fd, string ip, uint16_t port){struct sockaddr_in sever;sever.sin_family = AF_INET;sever.sin_addr.s_addr = inet_addr(ip.c_str());sever.sin_port=htons(port);if (connect(fd, (struct sockaddr *)&sever, sizeof(sever)) == 0){cout << "connect success!" << endl;}else{cout << "connect error" << endl;exit(5);}}
};

Sock.hpp封装了socket套接字的相关接口,方便后续进行使用。

Protocol.hpp

#pragma once
#include <iostream>
#include <string>
using namespace std;// 客户端发送请求
typedef struct request
{int x;int y;char op;} request_t;// 服务端做出响应(回应)
typedef struct response
{int code;   // code表示sever端计算的结果是否正确int result; // 表示计算的结果
} response_t;

可以理解为这是我们定制的一个协议,也就是结构化的数据。客户端发送request请求,服务器端发送response回应。 

 CalClient.cc

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Protocol.hpp"
#include "Sock.hpp"
#include <unistd.h>
#include <string.h>using namespace std;int main(int args, char *argv[])
{// 1.创建套接字文件int fd = Socket::Sock();// 2.发送链接Socket::Connect(fd, argv[1], atoi(argv[2]));// 3.发送请求request_t req;memset(&req, 0, sizeof(req));cout << "请输入x: ";cin >> req.x;cout << "请输入y: ";cin >> req.y;cout << "请输入op: ";cin >> req.op;write(fd, &req, sizeof(req));// 写都是输入型参数,读都是输出型参数// 4.获取回应response_t res;memset(&res, 0, sizeof(res));size_t s = read(fd, &res, sizeof(res));if (s == sizeof(res)){cout << "获取到了回应: " << res.code << " " << res.result << endl;}return 0;
}

client客户端,发送要计算的数据,将其打包成为request请求发送给sever服务器端,并接收sever服务器端的回应。 

要注意的是一般情况下write接口中传入输入型参数,read中传入输出型参数。

CalSever.cc

#include <iostream>
#include "Sock.hpp"
#include "Protocol.hpp"
#include <pthread.h>
#include <unistd.h>
#include <string.h>
using namespace std;// 5.提供服务
void *handle(void *args)
{int newfd = *(int *)args;delete (int *)args;// 获取请求request_t req;size_t s = read(newfd, &req, sizeof(req));if (s == sizeof(req)){// 处理请求response_t res = {0, 0};switch (req.op){case '+':res.result = req.x + req.y;break;case '-':res.result = req.x - req.y;break;case '*':res.result = req.x * req.y;break;case '/':if (req.y == 0){res.code = 1;cout << "除零错误" << endl;break;} // 除零错误res.result = req.x / req.y;break;case '%':if (req.y == 0){res.code = 2;cout << "除零错误" << endl;break;}// 除零错误res.result = req.x % req.y;break;default:res.code = 3; // 操作符非法cout << "请输入合法的操作符 " << endl;break;}cout << "request: " << req.x << req.op << req.y << endl;// 做出回应write(newfd, &res, sizeof(res));}close(newfd);
}int main(int args, char *argv[])
{// 1.创建套接字文件int listenfd = Socket::Sock();// 2.绑定IP和端口号Socket::Bind(listenfd, atoi(argv[1]));// 3.进行监听Socket::Listen(listenfd);for (;;){// 4.获取连接int fd = Socket::Accept(listenfd);int *newfd = new int(fd);pthread_t tid;pthread_create(&tid, nullptr, handle, (void *)newfd);}return 0;
}

sever服务器端获取client端发送的request请求,并向client客户端做出response回应,将最终的计算结果返回。 

 运行结果如下。

运行结果符合预期。

情景二:制造一个网络计算器小程序(使用序列化和反序列化)。

我们使用json第三方库进行序列化和反序列化。

Protocol.hpp

#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
using namespace std;// 客户端发送请求
typedef struct request
{int x;int y;char op;} request_t;// 服务端做出响应(回应)
typedef struct response
{int code;   // code表示sever端计算的结果是否正确int result; // 表示计算的结果
} response_t;//  request_t -> string
string SerializeRequest(const request_t &req)
{// 序列化Json::Value root; // 可以承装任何对象, json是一种kv式的序列化方案root["datax"] = req.x;root["datay"] = req.y;root["operator"] = req.op;Json::FastWriter writer;string json_string = writer.write(root);return json_string;
}// string -> request_t
void DeserializeRequest(const string &json_string, request_t &out)
{// 反序列化Json::Reader reader;Json::Value root;reader.parse(json_string, root);out.x = root["datax"].asInt();out.y = root["datay"].asInt();out.op = (char)root["operator"].asInt();
}string SerializeResponse(const response_t &resp)
{//序列化Json::Value root;root["code"] = resp.code;root["result"] = resp.result;Json::FastWriter writer;string res = writer.write(root);return res;
}void DeserializeResponse(const string &json_string, response_t &out)
{// 反序列化Json::Reader reader;Json::Value root;reader.parse(json_string, root);out.code = root["code"].asInt();out.result = root["result"].asInt();
}

序列化中有Value类对象和Writer类对象,Value类对象是一个万能对象是一个kv结构,可以接收任何对象。Writer类对象进行结构化数据转为字符串。

反序列化中有Value类对象和Reader类对象,Value对象和序列化一样,Reader类对象实现字符串转为结构化对象。

CalClient.cc

#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Protocol.hpp"
#include "Sock.hpp"
#include <unistd.h>
#include <string.h>using namespace std;int main(int args, char *argv[])
{// 1.创建套接字文件int fd = Socket::Sock();// 2.发送链接Socket::Connect(fd, argv[1], atoi(argv[2]));// 3.发送请求request_t req;memset(&req, 0, sizeof(req));cout << "请输入x: ";cin >> req.x;cout << "请输入y: ";cin >> req.y;cout << "请输入op: ";cin >> req.op;// 对req进行序列化,然后写入string json_string = SerializeRequest(req);write(fd, json_string.c_str(), json_string.size());// 写都是输入型参数,读都是输出型参数// 4.获取回应// 对获取到的回应进行反序列化char buffer[1024];size_t s = read(fd, buffer, sizeof(buffer) - 1);if (s > 0){buffer[s] = 0;response_t res;memset(&res, 0, sizeof(res));string json_string1 = buffer;DeserializeResponse(json_string1, res);cout << "获取到了回应: " << res.code << " " << res.result << endl;}return 0;
}

client端先对发送的结构化请求序列化成字符串,然后进行序列化字符串的发送,最终对从sever端收到的序列化字符串进行反序列化成结构化响应。 

CalSever.cc

#include <iostream>
#include "Sock.hpp"
#include "Protocol.hpp"
#include <pthread.h>
#include <unistd.h>
#include <string.h>
using namespace std;// 5.提供服务
void *handle(void *args)
{int newfd = *(int *)args;delete (int *)args;// 获取请求,对接受到的request请求进行反序列化char buffer[1024];request_t req;memset(&req, 0, sizeof(req));size_t s = read(newfd, buffer, sizeof(buffer) - 1);if (s > 0){buffer[s] = 0;string jsonstring = buffer;DeserializeRequest(jsonstring, req);// 处理请求response_t res = {0, 0};switch (req.op){case '+':res.result = req.x + req.y;break;case '-':res.result = req.x - req.y;break;case '*':res.result = req.x * req.y;break;case '/':if (req.y == 0){res.code = 1;cout << "除零错误" << endl;break;} // 除零错误res.result = req.x / req.y;break;case '%':if (req.y == 0){res.code = 2;cout << "除零错误" << endl;break;}// 除零错误res.result = req.x % req.y;break;default:res.code = 3; // 操作符非法cout << "请输入合法的操作符 " << endl;break;}cout << "request: " << req.x << req.op << req.y << endl;// 做出回应// 对回应进行序列化string json_string1 = SerializeResponse(res);write(newfd, json_string1.c_str(), json_string1.size());}close(newfd);
}int main(int args, char *argv[])
{// 1.创建套接字文件int listenfd = Socket::Sock();// 2.绑定IP和端口号Socket::Bind(listenfd, atoi(argv[1]));// 3.进行监听Socket::Listen(listenfd);for (;;){// 4.获取连接int fd = Socket::Accept(listenfd);int *newfd = new int(fd);pthread_t tid;pthread_create(&tid, nullptr, handle, (void *)newfd);}return 0;
}

sever端先对从client端收到的序列化字符串数据进行反序列化成结构化请求, 然后最终将结构化响应序列化成字符串发送给client端。

运行结果如下。

运行结果符合预期。 

以上便是本期的序列化和反序列化所有内容,需要注意的是,不论是我们今天写的简单计算器小程序,和前两期写的基于TCP和UDP的网络小程序都其实是处于应用层的。

本期内容到此结束^_^ 

http://www.yayakq.cn/news/393098/

相关文章:

  • 网页游戏网站mhn通付盾 网站建设公司
  • 平顶山市城乡建设职工培训网站wordpress采集 知乎
  • 网站推广的方法有哪些建设网站必备条件
  • 网站后台编辑器不能正常显示教育平台网站建设
  • 做ppt用什么网站国内设计的企业网站
  • seo站群优化技术软件项目实施流程八个阶段
  • 网站手机客户端如何开发沈阳企业自助建站
  • 山东城市建设厅网站中国建设网建筑通
  • 上海网站建设选缘魁包头网站建设公司哪家好
  • 教育培训手机网站模板下载产品开发项目管理全流程
  • 网站用什么系统好用设计购物网站的意义
  • 青岛市崂山区城乡建设局网站优秀的wordpress博客
  • 网站开发主要职责南昌企业网站开发
  • 网站建设力度不够论文宁夏建设监理协会网站
  • 互联网站备案信息农商1号的网站建设费
  • 建设网站费用多少钱网站栏目优化
  • 网站专题制作wordpress浮动插件
  • 盖县网站开发妖姬直播
  • 网站建设的原因有什么建筑工地招工招聘信息平台
  • 浙江建设三类人员报名网站装饰公司名称大全简单大气
  • 好看的网站 你明白吗wordpress for sae4.5
  • 外贸网站设计的公司怎么样能注册公司
  • 蚌埠网站制作大宗商品采购平台
  • 钢铁行业公司网站模板网站设计的步骤
  • 昆明网站搜索引擎优化网站建设公众
  • 四川成都私人网站建设免费网站注册平台
  • 随州网站建设学校互联网网站建设公司
  • 网站快速收录教程腾讯企业邮箱免费
  • 给菠菜网站做外包怎么在亚马逊上开店铺
  • 如何下载js做的网站网站建设详细流