自定义协议的网络计算器项目
源码链接:NetworkComputer_CustomProtocol_V3 · 周不才/cpp_linux study - 码云 - 开源中国
自定义协议(添加/去除报头,序列化/反序列化)Custom.hpp:
//自定义协议:包含自定义格式的序列化和反序列化、添加报头、去除报头操作
#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <memory>//提供智能指针
#include "Log.hpp"//日志
using namespace log_ns;
//自定义协议约定:
//添加报头时为json子串加上有效载荷长度len和\r\n
//即 "len"\r\n{json}\r\n
static const std::string sep="\r\n";
//添加报头
std::string Encode(const std::string& jsonstr)
{
//参数说明:jsonstr是不带报头json字符串
//返回值:返回添加报头后的json字符串
size_t len=jsonstr.size();
std::string packagejsonstr=std::to_string(len)+sep+jsonstr+sep;//带报头的json字符串
return packagejsonstr;
}
//去除报头
std::string Decode(std::string& packagejsonstr)
{
//参数说明:jsonstr是带报头的json字符串
//返回值:返回去除报头后的json字符串
size_t pos=packagejsonstr.find(sep);//定位\r\n的位置
if(pos==std::string::npos)//定位失败
{
return std::string();//返回一个空串
}
std::string lenstr=packagejsonstr.substr(0,pos);//取出"len"
int len=std::stoi(lenstr);//json字符串长度
int total=lenstr.size()+len+sep.size()*2;//计算完整的报文长度,即"len"\r\n{json}\r\n长度
if(packagejsonstr.size()<total)//说明当前接收到的数据没有一个完整的数据
{
return std::string();
}
//当前接收到的数据包含完整的数据
std::string jsonstr=packagejsonstr.substr(pos+sep.size(),len);//开始提取有效数据(即json字符串)
packagejsonstr.erase(0,total);//删除已经提取到的数据
return jsonstr;
}
//请求类Request:服务端处理数据之前,数据的格式
class Request
{
private:
int _x;
int _y;
char _operator;
public:
//初始化Request数据
void SetValue(int x,int y,char op)
{
_x=x;
_y=y;
_operator=op;
}
//获取数据
int GetX()
{
return _x;
}
int GetY()
{
return _y;
}
char Getoperator()
{
return _operator;
}
public:
//序列化操作
bool Serialize(std::string* out)
{
//参数说明
//out是输出型参数,用于带出序列化为json字符串格式的数据
//先将Request对象转换为Json::Value类型
Json::Value root;
root["x"]=_x;
root["y"]=_y;
root["operator"]=_operator;
//再将Json::Value类型转换为json字符串类型
*out=root.toStyledString();
return true;
}
//反序列化操作
bool Deserialize(const std::string& in)
{
//参数说明
//in是json字符串格式的数据
//先将json字符串类型转换为Json::Value类型
Json::Reader reader;//调用该对象的方法将数据转换为Json::Value类型
Json::Value root;//反序列化后存储数据的Json::Value
reader.parse(in,root);//将数据转换为Json::Value类型
//再将Json::Value类型转换为Request对象
_x=root["x"].asInt();
_y=root["y"].asInt();
_operator=root["operator"].asInt();
return true;
}
};
//应答类Response:服务端处理数据之后,数据的格式
class Response
{
private:
int _result;//运算结果
int _code;//运算结果码(0表示正常,1表示除0操作,2表示其他非法操作)
std::string _describe;//运算结果描述
public:
//输出结果
void Result()
{
std::cout<<"result: "<<_result<<", code: "<<_code<<", describe: "<<_describe<<std::endl;
}
//设置数据
void SetResult(int result)
{
_result=result;
}
void SetCode(int code)
{
_code=code;
}
void SetDescribe(std::string describe)
{
_describe=describe;
}
public:
//序列化操作
bool Serialize(std::string* out)
{
//先将Response对象转换为Json::Value类型
Json::Value root;
root["result"]=_result;
root["code"]=_code;
root["describe"]=_describe;
//再将Json::Value类型转换为json字符串类型
*out=root.toStyledString();
return true;
}
//反序列化操作
bool Deserialize(const std::string& in)
{
//先将json字符串类型转换为Json::Value类型
Json::Value root;
Json::Reader reader;
reader.parse(in,root);
//再将Json::Value类型转换为Response对象
_result=root["result"].asInt();
_code=root["code"].asInt();
_describe=root["describe"].asString();
return true;
}
};
//工厂模式:调用函数直接返回Request对象和Response对象
class Factory
{
public:
//构建Request对象
static std::shared_ptr<Request> BuildRequest()
{
return std::make_shared<Request>();
}
//构建Response对象
static std::shared_ptr<Response> BuildResponse()
{
return std::make_shared<Response>();
}
};