一、安装
1、安装依赖环境
sudo apt-get install pkg-config
sudo apt-get install autoconf automake libtool make g++ unzip
sudo apt-get install libgflags-dev libgtest-dev
sudo apt-get install clang libc++-dev
2、下载源码
国内镜像(githup上下载超慢,尤其是后面的submodule)
git clone https://gitee.com/mirrors/grpc-framework grpc
3、修改submodule
cd grpc
cat .gitmodules // 查看文件里的submodule, 将GitHub改成Gitee
4、更新submodule
cd grpc
git submodule update --init
5、安装gRPC
cd grpc
mkdir build
cd build
// 指定安装路径 /usr/local
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j2
sudo make install
二、测试
代码结构,这里客户端分为C++版和Python两个版本
├── client.py
└── ubuntu
├── client_cpp
│ ├── CMakeLists.txt
│ └── main.cpp
├── protos
│ ├── helloworld.grpc.pb.cc
│ ├── helloworld.grpc.pb.h
│ ├── helloworld.pb.cc
│ ├── helloworld.pb.h
│ ├── helloworld.proto
│ ├── helloworld_pb2.py
│ └── helloworld_pb2_grpc.py
└── server_cpp
├── CMakeLists.txt
└── main.cpp
1、proto文件
helloworld.proto
syntax = "proto3";
option java_package = "ex.grpc";
package helloworld;
message Reply {
int32 result = 1;
}
message HelloMessage {
int32 a = 1;
int32 b = 2;
}
service TestServer {
rpc hello_request (HelloMessage) returns (Reply) {}
}
生成c++和python对应的文件
(1)C++:
cd protos
protoc --cpp_out=. helloworld.proto
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
这里会报错:pro-gen-grpc插件没找到,全局搜索了下这个插件 是在目录下/home/package/build_grpc/grpc/build/grpc_cpp_plugin
为什么在编译源码时,没将build下的动态库放到系统环境/usr/local/bin下
两种解决方法:
1.可自己将上面插件路径设置到环境变量
2.将该插件拷贝到/usr/local/bin目录下
生成的目录:
(2)Python:
cd protos
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
2、gRPC服务端(C++)
main.cpp
#include <string>
#include <grpcpp/grpcpp.h>
#include "protos/helloworld.grpc.pb.h"
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
using helloworld::TestServer;
using helloworld::HelloMessage;
using helloworld::Reply;
class HelloServiceImplementation final : public TestServer::Service {
Status hello_request(
ServerContext* context,
const HelloMessage* request,
Reply* reply
) override {
int a = request->a();
int b = request->b();
reply->set_result(a * b);
return Status::OK;
}
};
void Run() {
std::string address("0.0.0.0:5000");
HelloServiceImplementation service;
ServerBuilder builder;
builder.AddListeningPort(address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<Server> server(builder.BuildAndStart());
std::cout << "Server listening on port: " << address << std::endl;
server->Wait();
}
int main(int argc, char** argv) {
Run();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(grpcdemo)
set(CMAKE_CXX_STANDARD 14)
find_package(Protobuf REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GRPCPP REQUIRED grpc++>=1.22.0)
include_directories(
${GRPCPP_INCLUDE_DIRS} # /usr/local/Cellar/grpc/1.29.1/include
${Protobuf_INCLUDE_DIRS} # /usr/local/include
)
link_directories(
${GRPCPP_LIBRARY_DIRS}
)
add_library(hellolibrary ../protos/helloworld.grpc.pb.cc ../protos/helloworld.pb.cc )
target_link_libraries(hellolibrary
protobuf::libprotobuf # 将protobuf加到hellolibrary, 因为在hellolibrary 使用了protobuf
)
add_executable(server_bin main.cpp)
target_link_libraries(server_bin
${GRPCPP_LIBRARIES}
hellolibrary
)
3、gRPC客户端(Python/C++)
client.py
import grpc
from protos import helloworld_pb2
from protos import helloworld_pb2_grpc
from google.protobuf.json_format import ParseDict
import time
class HelloBusiness(object):
def __init__(self):
super(HelloBusiness, self).__init__()
self.ip = "127.0.0.1"
self.port = 5000
self.client_init()
def client_init(self):
"""
gRPC客户端初始化
:return: None
"""
self.channel = grpc.insecure_channel('{}:{}'.format(self.ip, self.port))
self.client = helloworld_pb2_grpc.TestServerStub(self.channel)
return None
def hello_business(self, msg):
"""
:param msg: request msg
:return:
"""
proto_data = helloworld_pb2.HelloMessage() #
ParseDict(msg, proto_data) # 格式化msg
response = self.client.hello_request.future(proto_data) # 向server发送数据
response.add_done_callback(self.hello_callback) # 回调函数, 发送数据使用异步[future]时, 必须加回调函数
return response
def hello_callback(self, future):
print(future.result().result)
print("callback")
class HelloWorld(HelloBusiness):
def hello(self, *args, **kwargs):
"""
:return: None
"""
self.hello_business({
"a": 1,
"b": 2,
})
return None
grpc_client = HelloWorld()
if __name__ == '__main__':
grpc_client.hello()
time.sleep(2)
C++
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "../protos/helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::TestServer;
using helloworld::HelloMessage;
using helloworld::Reply;
class GreeterClient {
public:
GreeterClient(std::shared_ptr<Channel> channel):stub_(TestServer::NewStub(channel)) {}
int say_hello(const std::string& user) {
HelloMessage request;
Reply reply;
ClientContext context;
request.set_a(21);
request.set_b(22);
Status status = stub_->hello_request(&context, request, &reply);
if (status.ok()) {
return reply.result();
} else {
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
return 0;
}
}
private:
std::unique_ptr<TestServer::Stub> stub_;
};
int main(int argc, char** argv) {
GreeterClient greeter(grpc::CreateChannel("127.0.0.1:5000", grpc::InsecureChannelCredentials()));
std::string user("world");
int reply = greeter.say_hello(user);
std::cout << "Greeter received: " << reply << std::endl;
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(grpcdemo)
set(CMAKE_CXX_STANDARD 14)
find_package(Protobuf REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(GRPCPP REQUIRED grpc++>=1.22.0)
include_directories(
${GRPCPP_INCLUDE_DIRS} # /usr/local/Cellar/grpc/1.29.1/include
${Protobuf_INCLUDE_DIRS} # /usr/local/include
)
link_directories(
${GRPCPP_LIBRARY_DIRS}
)
add_library(hellolibrary ../protos/helloworld.grpc.pb.cc ../protos/helloworld.pb.cc )
target_link_libraries(hellolibrary
protobuf::libprotobuf # 将protobuf加到hellolibrary, 因为在hellolibrary 使用了protobuf
)
add_executable(client_bin main.cpp)
target_link_libraries(client_bin
${GRPCPP_LIBRARIES}
hellolibrary
)