Asio22-GrpcConnection

Asio22-GrpcConnection

1.0 什么是rpc

RPC(Remote Procedure Call) - 远程过程调用。

简单来说,就是让你能够像调用本地函数一样调用远程服务器上的函数。

2.0 什么是grpc

gRPC 是 Google 开发的一个高性能、开源的 RPC 框架。

核心特性

  • 基于 HTTP/2 - 支持多路复用、头部压缩等
  • 使用 Protobuf - 高效的二进制序列化协议
  • 跨语言 - 自动生成多语言客户端
  • 强类型 - 编译时类型检查
特性 RESTful API gRPC
协议 HTTP/1.1 HTTP/2
数据格式 JSON/XML Protobuf (二进制)
性能 中等 优秀
浏览器支持 完美 需要网关
开发体验 简单灵活 类型安全,代码生成
流式支持 有限 原生支持
适用场景 面向浏览器、第三方集成 微服务、内部系统、高性能需求

选择建议:

  • 需要高性能内部通信 → gRPC
  • 面向浏览器或移动端 → REST/GraphQL
  • 微服务架构 → gRPC
  • 快速原型、第三方集成 → REST
  • 流式数据传输 → gRPC

3.0 通信流程

gRPC 通信模型

// 1. 定义接口 (calculator.proto)
service Calculator {
  rpc Add (AddRequest) returns (AddResponse);
}

message AddRequest {
  int32 a = 1;
  int32 b = 2;
}

message AddResponse {
  int32 result = 1;
}
// 2. 服务端实现
class CalculatorServiceImpl : public Calculator::Service {
  grpc::Status Add(grpc::ServerContext* context, 
                   const AddRequest* request, 
                   AddResponse* response) override {
    response->set_result(request->a() + request->b());
    return grpc::Status::OK;
  }
};
// 3. 客户端调用
auto stub = Calculator::NewStub(channel);
AddRequest request;
request.set_a(10);
request.set_b(20);

AddResponse response;
grpc::Status status = stub->Add(&context, request, &response);
cout << "Result: " << response.result() << endl;  // 输出 30

4.0 代码

双方共享的数据结构protobuf文件

// demo.proto
syntax="proto3";

package demo;

service Greeter{
    rpc SayHello (HelloRequest) returns (HelloReply){}
}

message HelloRequest {
    string message = 1;

}

message HelloReply {
    string message = 1;
}

然后调用protoc --grpc_out=. --plugin=protoc-gen-grpc=$(which grpc_cpp_plugin) ./demo.proto 生成.grpc.pb.cc/h 和.pb.cc/h文件

服务器端

#include "demo.grpc.pb.h"
#include "demo.pb.h"
#include <algorithm>
#include <grpcpp/grpcpp.h>
#include <iostream>
#include <string>

class GreeterServiceImpl final : public demo::Greeter::Service {
public:
    ::grpc::Status SayHello(::grpc::ServerContext* context, const ::demo::HelloRequest* request, ::demo::HelloReply* reply)
    {

        std::cout << "Received message: " << request->message() << std::endl;

        std::string prefix("Grpc received and to upper case:");
        std::string upperstr = request->message();
        std::transform(upperstr.begin(), upperstr.end(), upperstr.begin(), ::toupper);

        reply->set_message(prefix + upperstr);
        return ::grpc::Status::OK;
    }
};

void RunServer()
{
    std::string address("0.0.0.0:9999");
    GreeterServiceImpl service;
    ::grpc::ServerBuilder builder;
    builder.AddListeningPort(address, ::grpc::InsecureServerCredentials());
    builder.RegisterService(&service);

    std::unique_ptr<::grpc::Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << address << std::endl;
    server->Wait();
}

int main()
{
    RunServer();
}

客户端

#include "demo.grpc.pb.h"
#include "demo.pb.h"
#include <grpcpp/grpcpp.h>
#include <iostream>
#include <memory>
#include <string>

class GreeterClientImpl {
public:
    GreeterClientImpl(std::shared_ptr<grpc::Channel> channel)
        : _stub(demo::Greeter::NewStub(channel))
    {
    }

    std::string SayHello(const std::string& name)
    {
        ::grpc::ClientContext context;
        demo::HelloReply response;
        demo::HelloRequest request;
        request.set_message(name);
        auto status = _stub->SayHello(&context, request, &response);
        if (status.ok()) {
            return response.message();
        }
        return "Error";
    }

private:
    std::unique_ptr<demo::Greeter::Stub> _stub;
};

int main(){
    std::shared_ptr<::grpc::Channel>channel = ::grpc::CreateChannel("127.0.0.1:9999", grpc::InsecureChannelCredentials());

    GreeterClientImpl client(channel);
    auto reply = client.SayHello("hello world");
    std::cout <<   "Greeter client received: " << reply << std::endl;
}
posted @ 2025-12-24 23:13  大胖熊哈  阅读(19)  评论(0)    收藏  举报