#c #g #protocol-buffers #grpc #protoc
#c #g #буферы протоколов #grpc #протокол
Вопрос:
Контекст
Я работаю с C уже около 5-6 месяцев и начинаю изучать gRPC. Я следил за многими учебными пособиями в Интернете, чтобы начать работу, но я хочу создать приложение для связи клиент-сервер с нуля. Возможно, это немного чересчур, но я делаю все возможное, чтобы понять, как заставить все это работать с нуля, а не загружать, набирать «сделать», а затем создавать рабочий продукт, который я не знаю, как внедрить в свои собственные проекты.
Цель: Создать и запустить простое взаимодействие C gRPC клиент-сервер
Версии
Я использую Vs-код для своей IDE.
- Протокол = libprotoc 3.17.3
- gRPC = 1.41.1
- сделать = 3,81
Файлы
математический тест.прото
syntax = "proto3"; option java_package = "ex.grpc"; package mathtest; // Defines the service service MathTest { // Function invoked to send the request rpc sendRequest (MathRequest) returns (MathReply) {} } // The request message containing requested numbers message MathRequest { int32 a = 1; int32 b = 2; } // The response message containing response message MathReply { int32 result = 1; }
server.cpp
#include lt;stringgt; #include lt;grpcpp/grpcpp.hgt; #include "mathtest.grpc.pb.h" using grpc::Server; using grpc::ServerBuilder; using grpc::ServerContext; using grpc::Status; using mathtest::MathTest; using mathtest::MathRequest; using mathtest::MathReply; class MathServiceImplementation final : public MathTest::Service { Status sendRequest( ServerContext* context, const MathRequest* request, MathReply* reply ) override { int a = request-gt;a(); int b = request-gt;b(); reply-gt;set_result(a * b); return Status::OK; } }; void Run() { std::string address("0.0.0.0:5000"); MathServiceImplementation service; ServerBuilder builder; builder.AddListeningPort(address, grpc::InsecureServerCredentials()); builder.RegisterService(amp;service); std::unique_ptrlt;Servergt; server(builder.BuildAndStart()); std::cout lt;lt; "Server listening on port: " lt;lt; address lt;lt; std::endl; server-gt;Wait(); } int main(int argc, char** argv) { Run(); return 0; }
client.cpp
#include lt;stringgt; #include lt;grpcpp/grpcpp.hgt; #include "mathtest.grpc.pb.h" using grpc::Channel; using grpc::ClientContext; using grpc::Status; using mathtest::MathTest; using mathtest::MathRequest; using mathtest::MathReply; class MathTestClient { public: MathTestClient(std::shared_ptrlt;Channelgt; channel) : stub_(MathTest::NewStub(channel)) {} int sendRequest(int a, int b) { MathRequest request; request.set_a(a); request.set_b(b); MathReply reply; ClientContext context; Status status = stub_-gt;sendRequest(amp;context, request, amp;reply); if(status.ok()){ return reply.result(); } else { std::cout lt;lt; status.error_code() lt;lt; ": " lt;lt; status.error_message() lt;lt; std::endl; return -1; } } private: std::unique_ptrlt;MathTest::Stubgt; stub_; }; void Run() { std::string address("0.0.0.0:5000"); MathTestClient client( grpc::CreateChannel( address, grpc::InsecureChannelCredentials() ) ); int response; int a = 5; int b = 10; response = client.sendRequest(a, b); std::cout lt;lt; "Answer received: " lt;lt; a lt;lt; " * " lt;lt; b lt;lt; " = " lt;lt; response lt;lt; std::endl; } int main(int argc, char* argv[]){ Run(); return 0; }
Steps taken for compilation
- Use
mathtest.proto
to create the necessary files via ‘protoc’ (or protobuf) by executing these:protoc --grpc_out=. --plugin=protoc-gen-grpc=/opt/homebrew/bin/grpc_cpp_plugin mathtest.proto
amp;protoc --cpp_out=. mathtest.proto
This creates the following files:
mathtest.pb.h
mathtest.pb.cc
mathtest.grpc.pb.h
mathtest.grpc.pb.cc
- Compile client.cpp amp; server.cpp files to create executable binaries using these commands:
g -std=c 17 client.cpp mathtest.pb.cc mathtest.grpc.pb.cc -o client 'pkg-config --libs protobuf grpc '
(NOTE: in this post, I use a single quote in the command line, but in the actual command I use a backtick; just wanted to make that clear)
Ошибки
Как вы можете заметить, я не могу приступить к компиляции сервера, потому что не могу сначала выполнить компиляцию клиента. После выполнения приведенной выше команды на шаге 2 компиляции это мой вывод:
g -std=c 17 client.cpp mathtest.pb.cc mathtest.grpc.pb.cc -o client `pkg-config --libs protobuf grpc ` client.cpp:4:10: fatal error: 'grpcpp/grpcpp.h' file not found #include lt;grpcpp/grpcpp.hgt; ^~~~~~~~~~~~~~~~~ 1 error generated. In file included from mathtest.pb.cc:4: ./mathtest.pb.h:10:10: fatal error: 'google/protobuf/port_def.inc' file not found #include lt;google/protobuf/port_def.incgt; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. In file included from mathtest.grpc.pb.cc:5: ./mathtest.pb.h:10:10: fatal error: 'google/protobuf/port_def.inc' file not found #include lt;google/protobuf/port_def.incgt; ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. make: *** [client] Error 1
Вот в чем мое настоящее замешательство…
У C intellisense нет проблем с поиском этих файлов. Мои переменные $PATH указывают на эти папки, и мой код VS включает путь, также указывающий на эти папки. Я не уверен, где я здесь ошибаюсь…
echo $PATH возвращает это:
/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew/include:/opt/homebrew/Cellar:/opt/homebrew/opt/libtool/libexec/gnubin:/usr/bin:/bin:/usr/sbin:/sbin:/Users/tzeller/.local/bin
Папки, о которых идет речь («google» и «grcpp»), находятся внутри /opt/homebrew/include
, и в них также хранятся необходимые файлы…
Что я упускаю??
Комментарии:
1. $PATH не имеет ничего общего с путями включения препроцессора.
Ответ №1:
Измените команду компиляции на
g -std=c 17 client.cpp mathtest.pb.cc mathtest.grpc.pb.cc -o client `pkg-config --libs --cflags protobuf grpc `
--cflags
Бит просит pkg-config указать необходимые параметры для настройки пути поиска заголовка (в моей системе -I/opt/homebrew/Cellar/grpc/1.41.1/include
и других).
Комментарии:
1. Спасибо, это сработало. Теперь перейдем к следующей возникшей проблеме… ошибки компоновщика.