医院做网站定位,网站竞价开户,开发游戏软件赚钱吗,网站建设交流平台自定义应用层协议
例子#xff1a;网络版本计算器
序列化反序列化
序列化#xff1a;将消息#xff0c;昵称#xff0c;日期整合成消息-昵称-日期
反序列化#xff1a;消息-昵称-日期-消息#xff0c;昵称#xff0c;日期
在序列化中#xff0c;定义一个结构体…自定义应用层协议
例子网络版本计算器
序列化反序列化
序列化将消息昵称日期整合成消息-昵称-日期
反序列化消息-昵称-日期-消息昵称日期
在序列化中定义一个结构体 struct Message{string message;string name;string data;};用这个结构体进行通信就是一种协议约定好的一种结构化字段就叫做协议
再比如 struct complate{int num1;int num2;char oper;
}序列化:将协议规定的结构化数据转换成字符串字节流 为什么发送效率变高
反序列化将字符串字节流转换成结构化数据 为什么方便与提取有效字段 协议定制procotol
1.直接传递struct
可以但使用范围很小
2.自己实现序列化反序列化
前备
客户端发送到服务端send/write函数其实是将自己的缓冲区拷贝到发送的缓冲区并没有经过网络。发送缓冲区的数据发多少怎么发出错怎么办一致由Tcp协议决定Tcp实际通信的时候是由双方操作系统之间进行通信同理read/recv也是拷贝函数将接收缓冲区拷贝到用户缓冲区。
既然send/write是拷贝函数也就是说当接收缓冲区为空发送缓冲区为满,双方进程都会被阻塞住。
Tcp为什么是全双工通信协议
当客户端进行发送服务端进行接收的同时服务端也可以进行发送客户端进行接收
当我们发送helloworld的时候对方一定收到helloworld吗
不一定当服务端的接受缓冲区只剩5个字节了客户端以为自己发了10个字节但事实上服务端此时只能读取到5个字节。这种特点我们叫做面向字节流
所以我们得明确报文和报文之间的边界 我们要解决的问题
a.解决结构化数据的序列化和反序列化
本质上是把结构化字段转换为字符串
b.解决用户区分报文边界问题
加入\n进行判断
namespace Proc_wrok
{const string Seq ;const string LineSep \n;//a op b//len\na op b\nvoid Encode(string message){int lenmessage.size();messageto_string(len)LineSepmessageLineSep;}//len\na op b\n//len//len\n//len\na op b//len\na op b\n//len\na op b\nlen\n//a op bbool Decode(string Package,string * message){auto LineSepPosPackage.find(\n);if(LineSepPosstring::npos) return false;int messagelenstoi(Package.substr(0,LineSepPos));int lensize(Package.substr(0,LineSepPos)).size();//没有完整的报文int total_sizemessagelenLineSep.size()*2lensize;if(Package.size()total_size) return false; //有完整的报文*messagePackage.substr(LineSepPosLineSep.size(),messagelen);//cout有完整的报文:*messageendl;Package.erase(0,total_size);return true;}class Request{public:Request() {}Request(int data_a, int data_b, char oper): _data_a(data_a), _data_b(data_b), _oper(oper){}void PrintDebug(){cout [ _data_a ] _oper [ _data_b ] ? endl;}void testDebug(){_data_a;_data_b;}// a op bvoid Serializa(string *message){string left to_string(_data_a);string right to_string(_data_b);*message left Seq _oper Seq right;}// a op bbool DesSerializa(string message){auto left message.find(Seq);if (left string::npos)return false;auto right message.rfind(Seq);if (right string::npos)return false;string numa message.substr(0, left);string oper message.substr(left 1, right - (left 1));if (oper.size() ! 1){cout Sep error endl;return false;}string numb message.substr(right 1);_data_a stoi(numa);_data_b stoi(numb);_oper oper[0];return true;}int GetA(){return _data_a;}int GetB(){return _data_b;}char GetOper(){return _oper;}private:int _data_a;int _data_b;char _oper;};class Result{public:Result() {}Result(int result, int code): _result(result), _code(code){}void Serializa(string *message){string left to_string(_result);string right to_string(_code);*message left Seq right;}// result codebool DesSerializa(string message){auto mid message.find(Seq);if (mid string::npos)return false;string result message.substr(0, mid);string code message.substr(mid 1);_result stoi(result);_code stoi(code);return true;}int GetResult(){return _result;}int GetCode(){return _code;}private:int _result;int _code;};}3.引入成熟的序列化反序列化
JSON
sudo yum install jsoncpp-devel 安装Jsoncpp库 JSON 版本的序列化与反序列化
void Serializa(string *message){Json::Value root;Json::FastWriter writer;root[_data_a]_data_a;root[_data_b]_data_b;root[_oper]_oper;*messagewriter.write(root);}// a op bbool DesSerializa(string message){Json::Value root;Json::Reader reader;bool retboolreader.parse(message,root);_data_aroot[_data_a].asInt();_data_broot[_data_b].asInt();_oper(char)(root[_oper].asInt());return retbool;}