在之前我们单纯使用muduo实现的时候,并没有考虑到tcp粘包之类的问题,只是进行一个返回
但是在实际应用过程中绝对不能这么草率,需要实现一个应用层协议来解决这些问题
包括序列化和反序列化,粘包
muduo定制的protobuf协议
在muduo源文件的example中有实现protobuf的客户端和服务端
我们可以先大致学习一下这里是怎么实现的,然后仿照使用一下
可以看到这里消息回调函数,这里面用的是ProtoBufCodec的onMessage函数
dispatcher是一个分发器,codec_是一个协议处理器
初始化里面是有一个注册消息回调函数,后面会有大用
而在这个类中,我们可以看到onMessage和send,其实就是针对protobuf处理的方法,也就是收到消息之后被调用的方法
在具体看这个onMessage处理函数之前,我们先看这个协议的结构是什么样的
有了这样的协议之后,就可以解决粘包问题
具体的函数调用逻辑是这样的(建议保存下来放大查看)
业务操作逻辑是这样的
proto文件
syntax = "proto3";
package Xu;
message TranslateRequest {
string msg = 1;
};
message TranslateResponse {
string msg = 1;
};
message AddRequest {
int32 num1 = 1;
int32 num2 = 2;
};
message AddResponse{
int32 result =1;
};
使用protoc --cpp_out=./ Request.proto
可以自动生成源文件和头文件
服务端代码编写
#include "protobuf/codec.h"
#include "protobuf/dispatcher.h"
#include "muduo/include/muduo/base/Logging.h"
#include "muduo/include/muduo/base/Mutex.h"
#include "muduo/include/muduo/net/EventLoop.h"
#include "muduo/include/muduo/net/TcpServer.h"
#include "Request.pb.h"
#include "TransLate.hpp"
#include "../logs/Xulog.h"
#include <iostream>
#include <unordered_map>
#include <unistd.h>
class Server
{
public:
using MessagePtr = std::shared_ptr<google::protobuf::Message>;
using TranslateRequestPtr = std::shared_ptr<Xu::TranslateRequest>;
using TranslateResponsePtr = std::shared_ptr<Xu::TranslateResponse>;
using AddRequestPtr = std::shared_ptr<Xu::AddRequest>;
using AddResponsePtr = std::shared_ptr<Xu::AddResponse>;
Server(int port)
: _server(&_baseloop, muduo::net::InetAddress("0.0.0.0", port),
"Server", muduo::net::TcpServer::kReusePort),
_dispatcher(std::bind(&Server::onUnknowMessage, this,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)),
_codec(std::bind(&ProtobufDispatcher::onProtobufMessage, &_dispatcher,
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))
{
// 注册业务请求处理函数
_dispatcher.registerMessageCallback<Xu::TranslateRequest>(std::bind(&Server::onTranslate, this, std::placeholders::_1<