Mac: https://github.com/Coxhuang/FKCpp/tree/master/gRPCDemo/macOS
Ubuntu: https://github.com/Coxhuang/FKCpp/tree/master/gRPCDemo/ubuntu
C++14
Python 3.8
macOS 10.5.15
Ubuntu 16.04
cmake 3.18.2
proto 3
Clion
使用brew安装
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
git clone https://gitee.com/mirrors/grpc-framework grpc
GitHub的submodule下载很慢很慢, 一天都下不下来
cd grpc
cat .gitmodules // 查看文件里的submodule, 将GitHub改成Gitee
cd grpc
git submodule update --init
cd grpc
mkdir build
cd build
// 指定安装路径 /usr/local
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make -j2
sudo make install
.
├── client.py
├── macOS
│ ├── client_cpp
│ │ ├── CMakeLists.txt
│ │ ├── build
│ │ └── 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
│ ├── build
│ └── main.cpp
└── 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
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对应的文件
注意: 生成.cc或者.h文件, macOS和Ubuntu两个平台的文件内容不一样,也就是说,不可以将在Mac下生成的*.cc和*.h文件在Ubuntu下使用**
cd protos
protoc --cpp_out=. helloworld.proto
protoc --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` helloworld.proto
生成:
helloworld.grpc.pb.cc
helloworld.grpc.pb.h
helloworld.pb.cc
helloworld.pb.h
cd protos
python3 -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. helloworld.proto
生成:
helloworld_pb2_grpc.py
helloworld_pb2.py
macOS下的代码,macOS和Ubuntu只有CMakeLists.txt不一样,具体的差异情况我的GitHub源码
不是说CMake是跨平台吗,为什么在macOS和Ubuntu的CMakeLists.txt不一样???
因为我在安装gPRC时,Mac使用brew安装,不是源码安装,导致在Mac下CMakeLists.txt不能使用find_package
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
macOS (macOS和Ubuntu的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
)
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)
#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
macOS (macOS和Ubuntu的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
)
'google/protobuf/port_def.inc' file not found
#include <google/protobuf/port_def.inc>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
原因: CMakeLists.txt中没有添加protobuf的头文件
解决 : include_directories( ${Protobuf_INCLUDE_DIRS} )
CMake Error at CMakeLists.txt:14 (find_package):
By not providing "FindgRPC.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "gRPC", but
CMake did not find one.
Could not find a package configuration file provided by "gRPC" with any of
the following names:
gRPCConfig.cmake
grpc-config.cmake
Add the installation prefix of "gRPC" to CMAKE_PREFIX_PATH or set
"gRPC_DIR" to a directory containing one of the above files. If "gRPC"
provides a separate development package or SDK, be sure it has been
installed.
原因: find_package(gRPC)
解决 : 将find_package(gRPC) 该为: find_package(PkgConfig REQUIRED) pkg_check_modules(GRPCPP REQUIRED grpc++>=1.22.0)