唯有梦想才配让你不安,
唯有行动才能解除你的不安。
--- 卢思浩 ---
1 知识回顾
上一篇文章我们讲解了协议的本质是双方能够看到的结构化数据。并通过传输层的底层理解了为什么read系列函数时全双工支持同时读写的:TCP传输层有两个缓冲区,分别接收和发送。最重要的是我们将TCP通信的代码进行的重构:
- 我们将Socket通信单独封装为一个类,负责Socket套接字的创建,bind绑定服务器端口号,进入监听模式…工作,基类Socket并不进行定义,只进行声明!具体实现由派生类TcpServer和UdpServer来进行
- TcpServer继承Socket类的所有方法,然后进行具体的函数定义!
- 上层的TcpServer直接底层使用TcpSocket对象就可以完成Socket系列操作,十分方便!
接下来我们要实现是这样的一个结构:
通信过程整体分为三层
- 传输层TcpServer:负责从Socket文件中获取链接,传输层不需要进行IO,获取到连接就让会话层通过连接获取数据!
- 会话层Service:根据传输层给的连接,从Sockfd文件中读取数据,解析出报文结构中的数据字符串,然后通过协议分离出结构化数据。该层只负责数据的解析,数据的处理交给应用层进行!
- 应用层Process:应用层是具有的业务逻辑,根据会话层解析出的数据,进行数据处理!
这样是一个非常非常优雅的封装操作!!!
2 序列化与编写协议
2.1 使用Json进行序列化
协议是IO的基础,只有协议确定下来,才可以进行通信。
我们这里想要实现一个网络计算器的应用,所以协议分为了两个类:Request和Response。分别作为传入的数据和传出的数据:
- Request:两个数字和一个运算符
- Response:结果数字 , 错误码 ,退出信息
他们是作为结构化的数据进行传输,那么想要进行传输就来到了最重要的部分序列化与反序列化!序列化与反序列化可以使用第三方库也可以自己进行编写。这里我们先使用第三方的Json库进行实现:
Jsoncpp 是一个用于处理 JSON 数据的 C++ 库。 它提供了将 JSON 数据序列化为字符串以及从字符串反序列化为 C++ 数据结构的功能。 Jsoncpp 是开源的, 广泛用于各种需要处理 JSON 数据的 C++ 项目中:
- 简单易用: Jsoncpp 提供了直观的 API, 使得处理 JSON 数据变得简单。
- 高性能: Jsoncpp 的性能经过优化, 能够高效地处理大量 JSON 数据。
- 全面支持: 支持 JSON 标准中的所有数据类型, 包括对象、 数组、 字符串、 数字、 布尔值和 null。
- 错误处理: 在解析 JSON 数据时, Jsoncpp 提供了详细的错误信息和位置, 方便开发者调试
在Linux中使用需要进行安装对应的JSON库:
ubuntu:sudo apt-get install libjsoncpp-dev
Centos: sudo yum install jsoncpp-devel
安装之后就可以进行使用了:
使用起来是十分方便的:
- Json::Value是最重要的类,这是对Json数据结构进程操作和表示的关键类
- 建立好类Json::Value之后就可以通过
[ ]操作root["x"] = _x;,像这样就可以进行赋值- 将Json数据结构转换为字符串依靠 Json::FastWriter 或 Json::StreamWriter都可以转换成字符串
Json::StyledWriter writer; std::string s = writer.write(root)
- 通过Json::Reader可以快速将字符串反序列化得到Json结构!
bool parsingSu***essful = reader.parse(json_string,root); // 访问 JSON 数据 std::string name = root["name"].asString(); int age = root["age"].asInt(); std::string city = root["city"].asString();
通过这样就就可以简洁的完成序列化与反序列化的工作!
2.2 编写协议
根据我们的需求在加入Json操作我们就可以把协议写出来,代码虽然很长但是很好理解:
- Request类中需要根据
int x , int y , char oper进行序列化生成字符串,也要能够通过字符串反序列化得到三个变量 - Response类中需要根据
int res , int code , std::string desc进行序列化生成字符串,也要能够通过字符串反序列化得到三个变量
#pragma once
#include <jsoncpp/json/json.h>
#include <string>
// 协议就是双方都认识的结构化数据
// "len"\r\n"{json}"\r\n
const std::string sep = "\r\n";
struct Request
{
public:
Request() {
}
Request(int x, int y, char oper) : _x(x), _y(y), _oper(oper)
{
}
~Request()
{
}
bool Serialize(std::string *out)
{
// 使用现成的 Json 库
Json::Value root;
root["x"] = _x;
root["y"] = _y;
root["oper"] = _oper;
Json::FastWriter writer;
std::string s = writer.write(root);
*out = s;
return true;
}
bool Deserialize(std::string &in)
{
Json::Value root; // 创建json对象
Json::Reader reader; // 读取
bool res = reader.