主要参考网上一些资料以及grpc源码中的示例,暂未包含异步
- 编译参考:
参考文档1:https://www.cnblogs.com/lontoken/p/6377048.html
参考文档2:https://yq.aliyun.com/articles/243432
参考文档3:https://www.cnblogs.com/oloroso/p/11121922.html
我主要参考的第一篇,但版本有些老,新版本可以参考后两篇,若使用编译好的库可以参考本文的工程
使用步骤:
- proto文件,这里我写了个例子,包括交互接口和输入输出信息结构
Protobuf3语言指南:https://blog.csdn.net/u011518120/article/details/54604615
- 自动生成grpc和protobuf的代码
首先将proto文件拷贝到protoc.exe文件目录下,打开命令行工具,cd到该目录,运行以下两行代码:
protoc.exe --cpp_out=./ TransMsg.proto
protoc.exe --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin.exe TransMsg.proto
在该目录下生成以下文件:
- 服务端代码示例
.h文件
#ifndef _ZZXG_Server_H__
#define _ZZXG_Server_H__
#include <iostream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
#include "TransMsg.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using TransMsg::RequestInfo;
using TransMsg::ReplyInfo;
using TransMsg::MutInterface;
class ZZXG_Server final: public MutInterface::Service
{
public:
ZZXG_Server();
~ZZXG_Server();
public:
Status RequestMsg(ServerContext* context, const RequestInfo* request, ReplyInfo* reply)override;
};
static void InitServer();
#endif // _ZZXG_Server_H__
.cpp文件
#include "ZZXG_Server.h"
ZZXG_Server::ZZXG_Server()
{
}
ZZXG_Server::~ZZXG_Server()
{
}
Status ZZXG_Server::RequestMsg(ServerContext* context, const RequestInfo* request, ReplyInfo* reply)
{
reply->set_asktype(request->asktype());
reply->set_asknum(request->asknum());
std::string reinfo = request->askname();
reply->set_remsg(reinfo);
return Status::OK;
}
void InitServer()
{
std::string server_address("0.0.0.0:50051");
ZZXG_Server service;
ServerBuilder builder;
// Listen on the given address without any authentication mechanism.
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
// Register "service" as the instance through which we'll communicate with
// clients. In this case it corresponds to an *synchronous* service.
builder.RegisterService(&service);
// Finally assemble the server.
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on " << server_address << std::endl;
// Wait for the server to shutdown. Note that some other thread must be
// responsible for shutting down the server for this call to ever return.
server->Wait();
}
int main(int argc, char** argv)
{
InitServer();
return 0;
}
- 客户端代码示例
.h文件
#ifndef _ZZXG_Client_H__
#define _ZZXG_Client_H__
#include <iostream>
#include <memory>
#include <string>
#include <grpc++/grpc++.h>
#include "TransMsg.grpc.pb.h"
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using TransMsg::RequestInfo;
using TransMsg::ReplyInfo;
using TransMsg::MutInterface;
class ZZXG_Client
{
public:
ZZXG_Client(std::shared_ptr<Channel> channel);
~ZZXG_Client();
public:
std::string Request(int askType, std::string askName, int askNum);
private:
std::unique_ptr<MutInterface::Stub> stub_;
};
#endif //_ZZXG_Client_H__
.cpp文件
#include "ZZXG_Client.h"
ZZXG_Client::ZZXG_Client(std::shared_ptr<Channel> channel)
:stub_(MutInterface::NewStub(channel))
{}
ZZXG_Client::~ZZXG_Client()
{}
std::string ZZXG_Client::Request(int askType,std::string askName,int askNum)
{
// 定义请求对象,并赋值.
RequestInfo request;
request.set_asktype(askType);
request.set_asknum(askNum);
request.set_askname(askName);
// 返回对象定义.
ReplyInfo reply;
// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;
// 调用请求函数.
Status status = stub_->RequestMsg(&context, request, &reply);
// 返回状态.
if (status.ok())
{
return reply.remsg();
}
else
{
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
int main(int argc, char** argv)
{
ZZXG_Client client(grpc::CreateChannel("127.0.0.1:50051", grpc::InsecureChannelCredentials()));
std::string reply = client.Request(1,"xbgsdgsdgsdgsdgsdgsdgsdgsdgsdgsdgsd",1);
std::cout << "ZZXG_Client received: " << reply << std::endl;
while(1)
{
Sleep(1);
}
return 0;
}
源码工程:链接:https://pan.baidu.com/s/1kaAS0-PX6DLr4bsCMmrDCQ
提取码:olx1
其中nuget 主要用于加载依赖,如果没有网络加载,可以将加载的包添加路径进行加载主要包括openssl和zlib,包括不同平台lib库和dll库,(若自己编译了相应版本的库,可直接添加到依赖中)
下载地址: https://pan.baidu.com/s/1JWHWd3_ylNbMdFCQaRJojg
提取码:mu7n
nuget添加程序包:
1、VS2015打开工程--》工具—》Nuget程序包管理器—》程序包管理器设置—》程序包源 新增一个名称和路径,设置路径为存放包文件夹的位置
2、工具—》Nuget程序包管理器—》管理解决方案的NuGet程序包,选择刚添加的程序包,安装到所需要的解决方案中
遇到问题:传输字符串含中文时传输不成功
注意:传输字符串结构 string时,不能包含中文,序列化的时候会出现截断数据,string这个类型带有检查功能,把protobuf中存在中文的string字段类型 改为bytes
string的序列化函数多以下代码
(参考:https://www.cnblogs.com/a9999/p/7283244.html)