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

中华门窗网怎么做网站老薛主机 wordpress 打不开

中华门窗网怎么做网站,老薛主机 wordpress 打不开,石家庄网站建设联系方式,价格合理的网站建设目录 一、序列化与反序列化概念 二、自定协议实现一个加法网络计算器 (一)TCP如何保证接收方的接收到数据是完整性呢? (二)自定义协议 (三)自定义协议的实现 1、基础类 2、序列化与反序列…

目录

一、序列化与反序列化概念

二、自定协议实现一个加法网络计算器

(一)TCP如何保证接收方的接收到数据是完整性呢?

(二)自定义协议

(三)自定义协议的实现

1、基础类

2、序列化与反序列化

3、报头的增删

4、从缓冲区内提取完整报文

5、自定协议在服务器与客户端的实现

三、使用Json进行序列化和反序列化

(一)概念

(二)Json的安装

(三)针对序列化和反序列化的改造


一、序列化与反序列化概念

        在之前的文章中,我们调用网络接口进行数据传输时都是使用字符串作为数据直接进行传输的,但是在一些场景中单个字符串是不能满足需要的,可能需要一个结构体或是数据结构,那么如何将结构体或数据结构进行网络传输呢?

        序列化:将数据结构或对象转换为字节流,以便它们可以存储到磁盘上、通过网络传输或在不同的程序间共享;

        反序列化:存储的字节流或文本数据重新转换为原来的数据结构或对象。这个过程用于恢复存储的或传输的数据,以便程序能再次使用它。

        当我们需要发送一个结构体时,我们可以先将其进行序列化转换为字节流再进行网络传输,而接收方可以通过将其反序列化从而恢复传输的数据,以此达到数据传输的目的。

二、自定协议实现一个加法网络计算器

(一)TCP如何保证接收方的接收到数据是完整性呢?

       UDP是面向数据报,而TCP是面向字节流的。

        在UDP协议传输数据时,由于数据的发送和接收都是按数据报的格式进行的,每个数据报是独立传输的。虽然UDP协议本身不保证数据的完整性和可靠性,但在网络传输没有出现丢包或错误的情况下,数据是完整的。

        但在使用TCP协议传输数据时,由于数据的发送和接收都是按字节流的形式进行的,发送和接收到的数据不一定是完整的,假如TCP的服务端读取速度小于TCP客户端的发送速度,那么在缓冲区一定堆积了大量的报文,那么如何从缓冲区内提取到一条完整的报文数据呢?

        其实我们调用接口进行网络数据传输本质实际是拷贝。发送方发送数据,接收方接收数据,本质实际是发送方缓冲区内容拷贝给接收方缓冲区。

        对于上述的问题,如果发送方发送数据的速度过快,导致接收方缓冲区内堆积了大量的报文,那么如何从大量数据中提取出一个完整的报文呢?

        实际上可以定制协议,以下是协议设计方式:

  • 定长(规定每个报文的固定长度)
  • 特殊符合(在报文之间加上特殊符合用于分割报文)
  • 自描述方式(数据本身描述其格式、大小等)

(二)自定义协议

        本文采用自描述方式设计自定协议:

        首先本文是针对加法计算器而做的协议,而这个协议不仅要包括数据的序列化和反序列化,还要有增添减少报头分割符的接口。除此之外,因为使用面向字节流进行输出,还要保证如何从缓冲区内提取一个完整的结构。

(三)自定义协议的实现

1、基础类

class Request
{
public:int _x;    //左操作数int _y;    //右操作数char _op;  //操作符
};
class Response
{
public:int _exitcode;  //退出码int _result;    //计算结果
};

2、序列化与反序列化

class Request
{
public:Request() {}Request(int x, int y, char op) : _x(x), _y(y), _op(op) {}//序列化bool serialize(string &out){out.clear();out += to_string(_x);out += SEP;out += _op;out += SEP;out += to_string(_y);return true;}//反序列化bool deserialize(const string &in){auto left = in.find(SEP);auto right = in.rfind(SEP);if (left == string::npos || right == string::npos || left == right)return false;if (right - left - SEP_LEN != 1)return false;string x_string = in.substr(0, left);string y_string = in.substr(right + SEP_LEN);if (x_string.empty() || y_string.empty())return false;_x = stoi(x_string);_y = stoi(y_string);_op = in[left + SEP_LEN];return true;}
public:int _x;int _y;char _op;
};
class Response
{
public:Response() {}Response(int exitcode, int result) : _exitcode(exitcode), _result(result) {}//序列化bool serialize(string &out){out.clear();out += to_string(_exitcode);out += SEP;out += to_string(_result);return true;}//反序列化bool deserialize(const string &in){auto index = in.find(SEP);if (index == string::npos)return false;string code = in.substr(0, index);string result = in.substr(index + SEP_LEN);if (code.empty() || result.empty())return false;_exitcode = stoi(code);_result = stoi(result);return true;}
public:int _exitcode;int _result;
};

3、报头的增删

#define SEP " "
#define SEP_LEN strlen(SEP)
#define SEP_LINE "\r\n"
#define SEP_LINE_LEN strlen(SEP_LINE)
//"text_len/r/text/r/n"
//增添报头
bool enLength(string &text)
{if (text.empty())return false;int len = text.size();string len_string = to_string(len);if (len_string.empty())return false;string ret;ret += len_string;ret += SEP_LINE;ret += text;ret += SEP_LINE;text = ret;return true;
}
//删除报头
bool deLength(const string &package, string &text)
{auto index = package.find(SEP_LINE);if (index == string::npos)return false;string len_string = package.substr(0, index);int len = stoi(len_string);text.clear();text = package.substr(index + SEP_LINE_LEN, len);return true;
}

4、从缓冲区内提取完整报文

bool recvPackage(const int &fd, string &inbuffer, string &text)
{while (true){char buffer[1024];ssize_t n = recv(fd, buffer, sizeof(buffer) - 1, 0);if (n > 0){buffer[n] = 0;inbuffer += buffer;auto index = inbuffer.find(SEP_LINE);string len_string = inbuffer.substr(0, index);int len = stoi(len_string);int total = len + SEP_LINE_LEN * 2 + len_string.size();if (inbuffer.size() < total){cout << "正在等待后续消息" << endl;continue;}text = inbuffer.substr(0, total);inbuffer.erase(0, total);break;}elsereturn false;}return true;
}

5、自定协议在服务器与客户端的实现

//服务端
void handlerEntery(const int &fd, func_t func){string inbuffer;while (1){// 收到ReqRequest req;string req_str, req_text;if (recvPackage(fd, inbuffer, req_str) == false)return;// 去报头cout << "接收数据:" << req_str << endl;bool ret = deLength(req_str, req_text);if (ret == false)logMessage(ERROR, "Server : deLength fail");cout << "接收数据正文:" << req_text << endl;// 反序列化ret = req.deserialize(req_text);if (ret == false)logMessage(ERROR, "Server : deserialize fail");// 计算Response resp;func(req, resp);// 序列化string resp_text;ret = resp.serialize(resp_text);if (ret == false)logMessage(ERROR, "Server : deserialize fail");cout << "发送数据:" << resp_text << endl;// 加报头ret = enLength(resp_text);if (ret == false)logMessage(ERROR, "Server : enLength fail");cout << "发送数据正文:" << resp_text << endl;// 发送Respsend(fd, resp_text.c_str(), resp_text.size(), 0);}}
//客户端
void run(){struct sockaddr_in addr;bzero(&addr, 0);addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr(_Sip.c_str());addr.sin_port = htons(_Sport);if (connect(_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1){cerr << strerror(errno) << endl;exit(2);}else{string inbuffer;while (true){// 读取数据string line;cout << " please input#\n";getline(cin, line);Request req = parseLine(line);// 序列化string req_text;bool ret = req.serialize(req_text);if (ret == false)logMessage(ERROR, "Client : serialize fail");// 加报头ret = enLength(req_text);if (ret == false)logMessage(ERROR, "Client : enLength fail");// 发数据send(_fd, req_text.c_str(), req_text.size(), 0);// 接收数据string resp_str, resp_text;if (!recvPackage(_fd, inbuffer, resp_str))continue;// 去报头ret = deLength(resp_str, resp_text);if (ret == false)logMessage(ERROR, "Client : deLength fail");// 反序列化Response resp;ret = resp.deserialize(resp_text);if (ret == false)logMessage(ERROR, "Client : deserialize fail");cout << "exitcode :" << resp._exitcode << "\tresulet : " << resp._result << endl;}}}

三、使用Json进行序列化和反序列化

(一)概念

        从上文可以得知,手动进行序列化和反序列化非常繁杂。实际上我们可以使用现成的方案。

        Json是一种轻量级的数据交换格式,广泛用于网络应用中,尤其是在客户端与服务器之间的数据交换。它易于阅读和编写,同时也便于机器解析和生成。

(二)Json的安装

        首先登录云服务器后输入指令:

sudo yum install -y jsonapp-devel

        使用Json除了需要引入头文件以外还需要在编译中加入 -ljsoncpp 选项。

#include <jsoncpp/json/json.h>
g++ -g -o Server Server.cpp -std=c++11 -ljsoncpp

(三)针对序列化和反序列化的改造

class Request
{
public:Request() {}Request(int x, int y, char op) : _x(x), _y(y), _op(op) {}//序列化bool serialize(string &out){Json::Value root;root["left"] = _x;root["right"] = _y;root["op"] = _op;Json::FastWriter writer;out = writer.write(root);        return true;}//反序列化bool deserialize(const string &in){Json::Value root;Json::Reader reader;reader.parse(in, root);_x = root["left"].asInt();_y = root["right"].asInt();_op = root["op"].asInt();return true;}
public:int _x;int _y;char _op;
};
class Response
{
public:Response() {}Response(int exitcode, int result) : _exitcode(exitcode), _result(result) {}//序列化bool serialize(string &out){Json::Value root;root["exitcode"] = _exitcode;root["result"] = _result;Json::FastWriter writer;out = writer.write(root);return true;}//反序列化bool deserialize(const string &in){Json::Value root;Json::Reader reader;reader.parse(in, root);_exitcode = root["exitcode"].asInt();_result = root["result"].asInt();return true;}public:int _exitcode;int _result;
};
http://www.yayakq.cn/news/725107/

相关文章:

  • 佛山做外贸网站案例wordpress编辑器 填满
  • 网站 模板 html网站建设验收评审标准
  • 网站 备案 在哪北京城乡建设集团有限公司官网
  • 网站建设公司做网站要多少费用阳谷网站建设费用
  • 网站安全加固上海市闵行区
  • 西安做网站维护的公司怎么查看网站啥系统做的
  • 做户外的网站网站优化需求表
  • 淘宝网页版入口官网seo群发软件
  • 总代理项目洛阳seo网站
  • 珠海网站建设珠海html网页设计模板下载
  • 长沙网站建设公司有哪些怎么提高网站权重
  • 网站维护中一般要多长时间综合信息网站模板
  • 主题网站策划设计书wordpress上传主题没图片
  • 建网站需要服务器吗化妆品品牌网站如何做
  • 网站已在别处备案怎么转入阿里云网站建设客户常问到的问题
  • 徐水住房建设局网站网上商城有哪几个
  • 建筑公司网站关键词有哪些网页设计教程
  • 科站网站网站建设的商业目的
  • 网站建设介绍怎么写wordpress编辑器内容
  • 计算机多媒体毕业设计网站建设设计网站推荐素材网站
  • 网站制作公司代理如何设计网站的链接
  • 网站开发需要工具营销型网站跟云网站
  • 网页与网站设计安徽网站建设有限公司
  • 网站快照工具做网站的的价位
  • qq刷赞网站咋做北京网络技术有限公司
  • 小型企业网站建站惠州品牌网站建设公司哪里有
  • 洛阳响应式建站邯郸装修公司
  • 安徽华夏网站建设北京百度快速排名
  • 网站导航栏模板怎么做玩具网站建设策划书流程
  • 有关做粪污处理设备的企业网站zencart 网站搬家