GRPC学习

主要参考网上一些资料以及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 主要用于加载依赖,如果没有网络加载,可以将加载的包添加路径进行加载主要包括opensslzlib,包括不同平台lib库和dll库,(若自己编译了相应版本的库,可直接添加到依赖中)

下载地址: https://pan.baidu.com/s/1JWHWd3_ylNbMdFCQaRJojg

提取码:mu7n

 

nuget添加程序包:

1VS2015打开工程--》工具Nuget程序包管理器》程序包管理器设置》程序包源  新增一个名称和路径,设置路径为存放包文件夹的位置

2、工具Nuget程序包管理器》管理解决方案的NuGet程序包,选择刚添加的程序包,安装到所需要的解决方案中

 

遇到问题:传输字符串含中文时传输不成功

注意:传输字符串结构 string时,不能包含中文,序列化的时候会出现截断数据,string这个类型带有检查功能,把protobuf中存在中文的string字段类型 改为bytes

string的序列化函数多以下代码

(参考:https://www.cnblogs.com/a9999/p/7283244.html)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章