Qt中调用gRPC

news2024/11/19 16:28:18

RPC是Remote Procedure Call的简称,中文叫远程过程调用。
gRPC是由 google开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于HTTP/2协议标准而设计,同时支持大多数流行的编程语言。

一.编译gRPC

操作系统:windows 10
Qt:5.12.10 MinGW64
CMake:3.13.3
NASM:2.16
这里因为项目需要,编译MinGW64版本的gRPC

1.克隆源码

grpc源码地址:https://github.com/grpc/grpc

git clone git@github.com:grpc/grpc.git

grpc源码下载完后,找到源码根目录下的.gitmodules文件,文件中是grpc编译所需要的子模块,将文件中的url由https地址改为ssh地址,即将https://替换为git@,将.com/替换为.com: 不这么做的话,很多子模块都会下载失败。
替换完成后的文件如下所示:

[submodule "third_party/abseil-cpp"]
	path = third_party/abseil-cpp
	url = git@github.com:abseil/abseil-cpp.git
[submodule "third_party/benchmark"]
	path = third_party/benchmark
	url = git@github.com:google/benchmark
[submodule "third_party/bloaty"]
	path = third_party/bloaty
	url = git@github.com:google/bloaty.git
[submodule "third_party/boringssl-with-bazel"]
	path = third_party/boringssl-with-bazel
	url = git@github.com:google/boringssl.git
[submodule "third_party/cares/cares"]
	path = third_party/cares/cares
	url = git@github.com:c-ares/c-ares.git
[submodule "third_party/envoy-api"]
	path = third_party/envoy-api
	url = git@github.com:envoyproxy/data-plane-api.git
[submodule "third_party/googleapis"]
	path = third_party/googleapis
	url = git@github.com:googleapis/googleapis.git
[submodule "third_party/googletest"]
	path = third_party/googletest
	url = git@github.com:google/googletest.git
[submodule "third_party/libuv"]
	path = third_party/libuv
	url = git@github.com:libuv/libuv.git
[submodule "third_party/opencensus-proto"]
	path = third_party/opencensus-proto
	url = git@github.com:census-instrumentation/opencensus-proto.git
[submodule "third_party/opentelemetry"]
	path = third_party/opentelemetry
	url = git@github.com:open-telemetry/opentelemetry-proto.git
[submodule "third_party/protobuf"]
	path = third_party/protobuf
	url = git@github.com:protocolbuffers/protobuf.git
[submodule "third_party/protoc-gen-validate"]
	path = third_party/protoc-gen-validate
	url = git@github.com:envoyproxy/protoc-gen-validate.git
[submodule "third_party/re2"]
	path = third_party/re2
	url = git@github.com:google/re2.git
[submodule "third_party/xds"]
	path = third_party/xds
	url = git@github.com:cncf/xds.git
[submodule "third_party/zlib"]
	path = third_party/zlib
	url = git@github.com:madler/zlib
	# When using CMake to build, the zlib submodule ends up with a
	# generated file that makes Git consider the submodule dirty. This
	# state can be ignored for day-to-day development on gRPC.
	ignore = dirty

接着下载子模块

cd grpc
git submodule update --init
#如果某个子模块下载失败,则可多次执行下方命令
git submodule update --recursive

2.CMake构建

在grpc目录下新建mingw64文件夹,打开CMake,选择源码路径和构建路径

点击Configure按钮,在弹出框中选择MinGW Makefiles,点击Finish按钮

配置完成,显示Configuring done。需要注意的是必须安装NASM,否则会Configure失败

点击Generate按钮,生成Makefile文件,显示Generating done。记住图中的几个路径,是gRPC最终安装的位置

3.编译

以管理员身份打开Qt 5.12.10(MinGW 7.3.0 64-bit),因为gPRC安装的路径在C盘,不用管理员身份可能会安装失败,提示如下错误:
CMake Error at cmake_install.cmake:36 (file):
  file cannot create directory: C:/Program Files (x86)/grpc/lib.  Maybe need
  administrative privileges.

进入mingw64目录

mingw32-make


我这编译的时候遇到了3个错误
①D:\grpc\src\core\lib\event_engine\tcp_socket_utils.cc:279:64: error: invalid conversion from 'const void*' to 'PVOID {aka void*}' [-fpermissive]
       inet_ntop(addr->sa_family, ip, ntop_buf, sizeof(ntop_buf)) != nullptr) {

解决方法:打开tcp_socket_utils.cc,将ip强制转换为void *
inet_ntop(addr->sa_family, (void *)ip, ntop_buf, sizeof(ntop_buf)) != nullptr) {
②D:\grpc\src\core\lib\event_engine\windows\iocp.cc:143:46: error: 'WSA_FLAG_NO_HANDLE_INHERIT' was not declared in this scope
                           wsa_socket_flags | WSA_FLAG_NO_HANDLE_INHERIT);
                                              ^~~~~~~~~~~~~~~~~~~~~~~~~~
D:\grpc\src\core\lib\event_engine\windows\iocp.cc:143:46: note: suggested alternative: 'UNW_FLAG_NHANDLER'
                           wsa_socket_flags | WSA_FLAG_NO_HANDLE_INHERIT);
解决方法:打开iocp.cc,将WSA_FLAG_NO_HANDLE_INHERIT改为0x80

DWORD IOCP::WSASocketFlagsInit() {
  DWORD wsa_socket_flags = WSA_FLAG_OVERLAPPED;
  /* WSA_FLAG_NO_HANDLE_INHERIT may be not supported on the older Windows
     versions, see
     https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
     for details. */
  SOCKET sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
                          wsa_socket_flags | 0x80);
  if (sock != INVALID_SOCKET) {
    /* Windows 7, Windows 2008 R2 with SP1 or later */
    wsa_socket_flags |= 0x80;
    closesocket(sock);
  }
  return wsa_socket_flags;
}

之所以这样改,是因为枚举WSA_FLAG_NO_HANDLE_INHERIT的值就是0x80,如下图所示

③D:/grpc/third_party/protobuf/src/google/protobuf/stubs/mutex.h:124:29: error: temporary of non-literal type 'google::protobuf::internal::CallOnceInitializedMutex<std::mutex>' in a constant expression
   constexpr WrappedMutex() {}
解决方法:这是由于protobuf的版本太高导致的,需手动下载protobuf-all-3.16.3,拷贝到./grpc/third_party/protobuf中,重新编译即可

4.安装

mingw32-make install

二.调用gRPC

grpc编译完后,在C:\Program Files (x86)\grpc目录下有编译好的grpc的应用程序、库文件、头文件。将地址C:\Program Files (x86)\grpc\bin添加到环境变量

1.编写.proto文件,生成cpp文件

新建文件helloworld.proto,输入如下内容

syntax = "proto3";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string greeting = 1;
}

打开cmd,进入helloworld.proto文件所在目录,依次执行如下命令

protoc.exe ./helloworld.proto --cpp_out=./
protoc.exe ./helloworld.proto --plugin=protoc-gen-grpc="C:/Program Files (x86)/grpc/bin/grpc_cpp_plugin.exe" --grpc_out=./

生成如下四个pb文件
helloworld.pb.h
helloworld.pb.cc
helloworld.grpc.pb.h
helloworld.grpc.pb.cc

2.客户端

在Qt中新建控制台工程GRPC_Client,将上面的四个pb文件添加到工程中,main.cpp修改为如下所示

#include <QCoreApplication>

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

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;

class GreeterClient {
public:
    GreeterClient(std::shared_ptr<Channel> channel)
        : stub_(Greeter::NewStub(channel)) {}

    // Assembles the client's payload, sends it and presents the response back
    // from the server.
    std::string SayHello(const std::string& user) {
        // Data we are sending to the server.
        HelloRequest request;
        request.set_name(user);

        // Container for the data we expect from the server.
        HelloReply reply;

        // Context for the client. It could be used to convey extra information to
        // the server and/or tweak certain RPC behaviors.
        ClientContext context;

        // The actual RPC.
        Status status = stub_->SayHello(&context, request, &reply);

        // Act upon its status.
        if (status.ok()) {
            return reply.greeting();
        } else {
            std::cout << status.error_code() << ": " << status.error_message()
                      << std::endl;
            return "RPC failed";
        }
    }

private:
    std::unique_ptr<Greeter::Stub> stub_;
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    GreeterClient greeter(
                grpc::CreateChannel("localhost:50051", grpc::InsecureChannelCredentials()));
    std::string user("world");
    std::string reply = greeter.SayHello(user);
    std::cout << "Greeter received: " << reply << std::endl;
    return a.exec();
}

3.服务端

在Qt中新建控制台工程GRPC_Server,将上面的四个pb文件添加到工程中,main.cpp修改为如下所示

#include <QCoreApplication>
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/health_check_service_interface.h>
#include "helloworld.grpc.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::Greeter;
using helloworld::HelloReply;
using helloworld::HelloRequest;

// Logic and data behind the server's behavior.
class GreeterServiceImpl final : public Greeter::Service {
  Status SayHello(ServerContext* context, const HelloRequest* request,
                  HelloReply* reply) override {
    std::string prefix("Hello ");
    reply->set_greeting(prefix + request->name());
    return Status::OK;
  }
};

void RunServer() {
  std::string server_address("0.0.0.0:50051");
  GreeterServiceImpl service;

  grpc::EnableDefaultHealthCheckService(true);
  grpc::reflection::InitProtoReflectionServerBuilderPlugin();
  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[])
{
    QCoreApplication a(argc, argv);

    RunServer();
    return a.exec();
}

4.pro文件配置

GRPC_Client.pro和GRPC_Server.pro中都要添加如下内容

GRPC_HOME="C:/Program Files (x86)/grpc"

INCLUDEPATH += $$GRPC_HOME/include

LIBS += -L$$GRPC_HOME/lib -lgrpc++ -lgrpc -lgpr -lgrpc_plugin_support -lgrpc_unsecure -lgrpc++_alts \
-lgrpc++_error_details -lgrpc++_reflection -lgrpc++_unsecure -lgrpcpp_channelz -laddress_sorting \
-lcares -labsl_bad_any_cast_impl -labsl_bad_optional_access -labsl_bad_variant_access -labsl_civil_time \
-labsl_cordz_info -labsl_cord -labsl_cordz_functions -labsl_cordz_handle -labsl_cord_internal \
-labsl_cordz_sample_token -labsl_exponential_biased -labsl_flags -labsl_flags_commandlineflag \
-labsl_flags_commandlineflag_internal -labsl_flags_config -labsl_flags_internal -labsl_flags_marshalling \
-labsl_flags_parse -labsl_flags_private_handle_accessor -labsl_flags_program_name -labsl_flags_reflection \
-labsl_flags_usage -labsl_flags_usage_internal -labsl_synchronization -labsl_graphcycles_internal -labsl_hash \
-labsl_city -labsl_hashtablez_sampler -labsl_log_severity -labsl_low_level_hash -labsl_periodic_sampler \
-labsl_random_internal_pool_urbg -labsl_random_internal_seed_material -labsl_random_internal_randen_hwaes_impl \
-labsl_random_distributions -labsl_random_internal_distribution_test_util -labsl_random_internal_platform \
-labsl_random_internal_randen -labsl_random_internal_randen_hwaes -labsl_random_internal_randen_slow \
-labsl_random_seed_gen_exception -labsl_random_seed_sequences -labsl_raw_hash_set -labsl_scoped_set_env \
-labsl_spinlock_wait -labsl_status -labsl_statusor -labsl_str_format_internal -labsl_strerror -labsl_symbolize \
-labsl_failure_signal_handler -labsl_examine_stack -labsl_stacktrace -labsl_leak_check \
-labsl_debugging_internal -labsl_demangle_internal -labsl_strings -labsl_strings_internal -labsl_malloc_internal \
-labsl_raw_logging_internal -labsl_throw_delegate -labsl_time -labsl_time_zone -labsl_int128 -labsl_base -lre2 \
-lupb -lprotobuf -llibprotoc -lzlib.dll -lssl -lcrypto -ldbghelp

LIBS += -lWS2_32 -lAdvapi32 -lbcrypt

DEFINES += _WIN32_WINNT=0x600

注:GRPC_HOME=“C:/Program Files (x86)/grpc” 路径加引号的原因是路径中存在空格

5.运行

先运行GRPC_Server,再运行GRPC_Client,结果如下所示

参考链接: https://blog.csdn.net/u014340533/article/details/125539126

原文链接:https://blog.csdn.net/caoshangpa/article/details/128402625

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/106791.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

百亿级流量的系统架构该怎么设计,今天就来教会你!

V-xin&#xff1a;ruyuan0330 获得600页原创精品文章汇总PDF 目录 一、前情提示二、清晰划分系统边界三、引入消息中间件解耦四、利用消息中间件削峰填谷五、手动流量开关配合数据库运维六、支持多系统同时订阅数据七、系统解耦后的感受八、下集预告 一、前情提示 上一篇文章…

吊炸天的云原生,到底是个啥

云原生技术里有很多技术、概念和术语&#xff0c;不了解的人&#xff0c;往往弄不清楚而一头雾水&#xff0c;这些概念都是啥&#xff0c;之间是什么关系&#xff1f;本文要说的就是这些。本文更多是科普和扫盲&#xff0c;无意面面俱到&#xff0c;也无意深入细节。 本文适合一…

Allegro如何合并同名网络铜皮操作指导

Allegro如何合并同名网络铜皮操作指导 Allegro可以将同名网络的铜皮合并起来,如下图,需要把下面两块铜皮合并成一块铜皮 具体操作如下 选择Shape选择merge shapes

剑指Offer-面试题1:整数除法——你真的会用Math.abs吗?

整数除法 题目要求 输入2个int型整数&#xff0c;它们进行除法计算并返回商&#xff0c;要求不得使用乘号*、除号/及求余符号%。当发生溢出时&#xff0c;返回最大的整数值。假设除数不为0。例如&#xff0c;输入15和2&#xff0c;输出15/2的结果&#xff0c;即7。 有问题的…

使用OpenCV的函数polylines()绘制多条相连的线段和多边形;使用函数fillPoly()绘制带填充效果的多边形

函数polylines()可用来根据点集绘制多条相连的线段&#xff0c;也可用来绘制多边形。 函数polylines()有两种原型&#xff0c;这里只向大家介绍比较常用的那种原型。 函数polylines()的C原型如下&#xff1a; void cv::polylines(InputOutputArray img,const Point *const *…

Power BI 11个必学官方示例数据案例(附下载链接)

在开始学习Power BI时&#xff0c;最大的问题就是不知道哪里找数据&#xff0c;或者有数据却对搭建看板毫无头绪&#xff0c; 不知道该从哪里下手。 本文收集整理了官网上最值得学习的11个案例&#xff0c;包括不同行业和分析方法&#xff0c;方便大家按需学习。点击标题即可转…

安徽省建设工程监理人员从业水平能力证书

安徽省建设监理协会会员单位从业人员是指已通过安徽省建设监理协会组织的从业水平能力认定考试&#xff0c;取得《安徽省建设工程监理人员从业水平能力证书》&#xff0c;并在工程建设中从事监理工作的监理工程师和监理员&#xff08;以下简称“监理工程师、监理员”&#xff0…

LLVM中矩阵Matrix的实现分析

1 背景说明 Clang提供了C/C语言对矩阵的扩展支持&#xff0c;以方便用户使用可变大小的二维数据类型来实现计算&#xff0c;目前该特性还是实验版&#xff0c;设计和实现都在变化中。LLVM目前设计为支持小型列矩阵&#xff08;column major&#xff09;&#xff0c;其对矩阵的…

Java字节码介绍

Java字节码 概述 学习 Java 的都知道&#xff0c;我们所编写的 .java 代码文件通过编译将会生成 .class 文件&#xff0c;最初的方式就是通过 JDK 的 javac 指令来编译&#xff0c;再通过 java 命令执行 main 方法所在的类&#xff0c;从而执行我们的 Java 程序。而在这中间所…

【矩阵论】6. 矩阵理论——算子范数

6.2 算子范数 6.2.1 定义 CnC^nCn 上任一向量范数 ∥X∥V\Vert X\Vert_V∥X∥V​ 都产生一个矩阵范数 ∥A∥max⁡x≠0{∥AX∥V∥X∥V}\Vert A\Vert\max_{x\neq 0}\limits \{\frac{\Vert AX\Vert_V}{\Vert X\Vert_V}\}∥A∥x0max​{∥X∥V​∥AX∥V​​} ,X∈CnX\in C^nX∈Cn…

Linux 管理联网 测试网络连通性 -- Ping 命令详解 tracepath命令详解

测试网络的连通性 # 我们测试网络的连通性&#xff0c;一般就是使用的 PIng 命令 Ping &#xff1a; 一般格式 &#xff1a; ping [ 选项 ] < 目标主机名 或 IP 地址 > 常用选项 &#xff1a; - c 数字 &#xff1a; 用于 设定本命令发出的 ICMP 消息包的…

限量,Alibaba首发“Java成长笔记”,差距不止一点点

前言 本文是为了帮大家快速回顾了Java中知识点&#xff0c;这套面试手册涵盖了诸多Java技术栈的面试题和答案&#xff0c;相信可以帮助大家在最短的时间内用作面试复习&#xff0c;能达到事半功倍效果。 本来想将文件上传到github上&#xff0c;但由于文件太大有的都无法显示…

CentOS7使用yum安装Golang(超详细)

使用yum安装Golang前言一、go语言介绍二、yum安装golang1.安装go版本为1.19.41.1执行yum install go&#xff08;报错&#xff09;1.2配置go的安装源1.3执行yum install golang1.4查看go的安装版本2.安装go版本为 1.11rc2&#xff08;这个参考&#xff0c;不用操作&#xff09;…

Docker镜像的原理

centos7系统 包括2部分&#xff0c; linux内核&#xff0c;作用是提供操作系统的基本功能&#xff0c;和机器硬件交互&#xff0c;如何读取磁盘数据&#xff0c;管理网络&#xff0c;使用C编写的&#xff0c;由linus的开发团队&#xff0c;内核只提供操作系统的基本功能和特性…

修改嵌入式 ARM Linux 内核映像中的文件系统

zImage 是编译内核后在 arch/arm/boot 目录下生成的一个已经压缩过的内核映像。通常我们不会使用编译生成的原始内核映像 vmlinux&#xff0c;因其体积很大。因此&#xff0c;zImage 是我们最常见的内核二进制&#xff0c;可以直接嵌入到固件&#xff0c;也可以直接使用 qemu 进…

C++的OpenCV中cv::minAreaRect的返回角度的数值范围是多少?

版本不一样的时候&#xff0c;返回也不一样。 我使用opencv/4.5.5。 下图是使用minAreaRect判定的角度&#xff0c;可以看到&#xff0c;数值范围是[0,90]&#xff0c;看起来很离谱。 画出这张图使用的程序如下&#xff1a; C int main() {std::string prefix1 "/mn…

SpringMvc+Thymeleaf实现数据渲染

Thymeleaf是spring boot推荐使用的模板语法&#xff0c;它可以完全替代 JSP 。 从代码层次上讲&#xff1a;Thymeleaf是一个java类库&#xff0c;它是一个xml/xhtml/html5的模板引擎&#xff0c;可以作为mvc的web应用的view层。 Thymeleaf 提供spring标准方言和一个与 SpringMV…

Ui自动化概念+Web自动化测试框架介绍

目录 UI 1.UI自动化测试概念:我们先明确什么是UI 2.为什么对UI采用自动化测试? 3.什么项目适合做UI自动化测试? 4.UI自动化测试介入时机 5.UI自动化测试所属分类 Web自动化测试框架介绍 2.Selenium框架介绍及特点: Web自动化测试环境搭建 2.元素定位(一) idclassna…

【数据结构】栈与集合类Stack

目录 一、栈 二、Java中的集合类之Stack 1、介绍 2、构造方法 3、常用方法 1.push 2.pop 3.peek 4.search 5.empty 三、实现Stack 1、准备字段 2、实现判空 3、实现压栈 4、实现出栈 5、实现获取栈尾元素 6、指定元素到栈顶的距离 一、栈 栈(stack)是一种比较…

Redis高可用之哨兵模式(第二部分)

引言 接上一篇&#xff0c;今天我们来聊一聊Redis的高可用的第二个解决方案&#xff1a;哨兵模式。 一、Redis哨兵模式 哨兵模式&#xff08;sentinel&#xff09;是Redis提供的高可用的解决方案之一。由一个或者多个sentinel示例组成的sentinel系统&#xff0c;可以监听任意…