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)

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