Context
I have been working with C++ for about the past 5-6 months and I'm beginning to learn gRPC. I have followed many tutorials online to get started, but I want to build a client-server communication app from scratch. Probably a bit too much, but I'm doing my best to understand how to get it all to work from the ground up rather than downloading, typing 'make', and then having a working product that I don't know how to implement into my own projects.
Goal: Create and run a simple C++ gRPC client-server communication
Versions
Using VSCode IDE.
Protoc = libprotoc 3.17.3
gRPC = 1.41.1
make = 3.81
Files
mathtest.proto
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 <string>
#include <grpcpp/grpcpp.h>
#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->a();
int b = request->b();
reply->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(&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;
}
client.cpp
#include <string>
#include <grpcpp/grpcpp.h>
#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_ptr<Channel> 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_->sendRequest(&context, request, &reply);
if(status.ok()){
return reply.result();
} else {
std::cout << status.error_code() << ": " << status.error_message() << std::endl;
return -1;
}
}
private:
std::unique_ptr<MathTest::Stub> 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 << "Answer received: " << a << " * " << b << " = " << response << 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 & 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 & 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)
Errors
As you may notice, I can't get to compiling the server because I can't get past the client compilation first. After executing the above command in step 2 of compilation, this is my output:
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 <grpcpp/grpcpp.h>
^~~~~~~~~~~~~~~~~
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 <google/protobuf/port_def.inc>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 <google/protobuf/port_def.inc>
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
make: *** [client] Error 1
Here's my real confusion...
C++ intellisense has no issues finding these files. My $PATH variables point to these folders, and my VS Code include path also point to these folders. I'm unsure where I am going wrong here...
echo $PATH returns this:
/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
The folders in question ('google' & 'grcpp') live within /opt/homebrew/include and they hold the necessary files as well...
What am I missing??
Change your compile command to
g++ -std=c++17 client.cpp mathtest.pb.cc mathtest.grpc.pb.cc -o client `pkg-config --libs --cflags protobuf grpc++`
The --cflags bit asks pkg-config to spit out the necessary parameters for setting the header search path (on my system -I/opt/homebrew/Cellar/grpc/1.41.1/include and others)
Related
I am testing the example code posted on the official libtorrent website (https://www.libtorrent.org/tutorial-ref.html). I pasted the code here:
#include <libtorrent/session.hpp>
#include <libtorrent/add_torrent_params.hpp>
#include <libtorrent/torrent_handle.hpp>
#include <libtorrent/magnet_uri.hpp>
int main(int argc, char const* argv[])
{
if (argc != 2) {
fprintf(stderr, "usage: %s <magnet-url>\n");
return 1;
}
lt::session ses;
lt::add_torrent_params atp = lt::parse_magnet_uri(argv[1]);
atp.save_path = "."; // save in current dir
lt::torrent_handle h = ses.add_torrent(atp);
// ...
}
I have already installed the libtorrent:
ldconfig -v | grep libtorrent
libtorrent-rasterbar.so.9 -\> libtorrent-rasterbar.so.9.0.0
I used the following command to compile the code:
g++ main.cpp -o run -ltorrent-rasterbar -lboost_filesystem-mt
However, I got errors:
main.cpp: In function 'int main(int, const char\*\*)':
main.cpp:12:3: error: 'lt' has not been declared
lt::session ses;
I also saw another solution, but it does not resolve the issue I am facing: How to compile a libtorrent(rasterbar) code ?
Does anyone know what caused this failure?
Accessing IIS webservice using Gsoap.
I have similar error as in this link shows that the error was solved compiling with -lssl.
I did the same thing in build as
g++ -o client client.cpp stdsoap2.cpp soapC.cpp soapDataManagementSoapProxy.cpp -I /usr/local/ssl/include -L/home/xavier/GSOAP/lib -lgsoapssl++ -L/usr/local/ssl/lib -lssl
My GSOAP lib was build with OpenSSL.
But I still have error as
SOAP 1.2 fault SOAP-ENV:Sender[no subcode]
"OpenSSL not installed: recompile with -DWITH_OPENSSL"
Detail: [no detail]
My test code is as follow. What could be wrong?
#include "soapDataManagementSoapProxy.h"
#include "DataManagementSoap.nsmap"
const char server[] = "https://XXXXXXX.com/XXXmanagement.asmx";
int main(int argc, char **argv)
{
DataManagementSoapProxy webinf;
webinf.soap_endpoint = server;
_tempuri__ReadTestData* a;
_tempuri__ReadTestDataResponse res;
int ret = webinf.ReadTestData(a, res);
if (webinf.error){
webinf.soap_stream_fault(std::cerr);
}
else{
//printf("result = %g\n", result);
std::cout << "Success " << std::endl;
}
webinf.destroy(); /* clean up mem */
return 0;
}
Solution for this issue is
#include "calc.nsmap"
#include "soapcalcProxy.h" // generated with soapcpp2 -j calc.h
calcProxy calc("https-server-endpoint-URL");
double sum;
soap_ssl_init(); // init SSL (just need to do this once in an application)
// soap_ssl_no_init(); // or prevent init OpenSSL when already initialized elsewhere in an application
if (soap_ssl_client_context(calc.soap,
SOAP_SSL_DEFAULT,
NULL, // no keyfile
NULL, // no keyfile password
"cacerts.pem", // trusted certificates (or use self-signed cacert.pem)
NULL, // no capath to trusted certificates
NULL // no random data to seed randomness
))
{
calc.soap_stream_fault(std::cerr);
exit(EXIT_FAILURE);
}
if (calc.add(1.23, 4.56, sum) == SOAP_OK)
I am currently trying to get a working tls websocket client running in C++ (which is a pain in the ass) and I have tried CPP Rest SDK as well as Websocket++. Both spit out a bunch of compile errors (see below). When I tried compiling it using Websocket++ without tls, it compiles so the error clearly is related to SSL.
I tried different OpenSSL versions (1.0.1, 1.0.2, 1.1.0), different C++ versions (11, 14 and even 17), and I just can't get it to compile.
I googled and none of the solutions worked. I am on Ubuntu 16 and the build command I am using looks like this:
g++ source/* -o test.out -Iinclude/ -std=c++14 -L/lib64 -lcurl -lboost_system -lssl -lcrypto -l pthread
Here are some of the errors:
/usr/include/boost/asio/ssl/detail/impl/openssl_init.ipp: In constructor ‘boost::asio::ssl::detail::openssl_init_base::do_init::do_init()’:
/usr/include/boost/asio/ssl/detail/impl/openssl_init.ipp:43:23: error: expected id-expression before ‘(’ token
mutexes_.resize(::CRYPTO_num_locks());
/usr/include/boost/asio/ssl/detail/impl/engine.ipp:221:9: error: ‘SSL_R_SHORT_READ’ was not declared in this scope
ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ),
And here is the basic source code:
#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream>
// pull out the type of messages sent by our config
typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr;
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
void on_close(client* c, websocketpp::connection_hdl hdl) {
c->get_alog().write(websocketpp::log::alevel::app, "Connection Closed");
}
int main(int argc, char* argv[]) {
client c;
std::string uri = "wss://gateway.discord.gg/";
if (argc == 2) {
uri = argv[1];
}
try {
// set logging policy if needed
c.clear_access_channels(websocketpp::log::alevel::frame_header);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
//c.set_error_channels(websocketpp::log::elevel::none);
// Initialize ASIO
c.init_asio();
// Register our handlers
c.set_open_handler(bind(&on_open,&c,::_1));
c.set_fail_handler(bind(&on_fail,&c,::_1));
c.set_message_handler(bind(&on_message,&c,::_1,::_2));
c.set_close_handler(bind(&on_close,&c,::_1));
// Create a connection to the given URI and queue it for connection once
// the event loop starts
websocketpp::lib::error_code ec;
client::connection_ptr con = c.get_connection(uri, ec);
c.connect(con);
// Start the ASIO io_service run loop
c.run();
} catch (const std::exception & e) {
std::cout << e.what() << std::endl;
} catch (websocketpp::lib::error_code e) {
std::cout << e.message() << std::endl;
} catch (...) {
std::cout << "other exception" << std::endl;
}
}
This was a long time ago but in case it helps, adding -lcrypto -lssl in the g++ cmd arguments solved the problem for me.
I'm learning cpp-netlib and I tried running the exmaple client given on the official website. The code is very simple:
#include <boost/network/protocol/http/client.hpp>
#include <iostream>
int main(int argc, char *argv[]) {
using namespace boost::network;
if (argc != 2) {
std::cout << "Usage: " << argv[0] << " [url]" << std::endl;
return 1;
}
http::client client;
http::client::request request(argv[1]);
request << header("Connection", "close");
http::client::response response = client.get(request);
std::cout << body(response) << std::endl;
return 0;
}
And here is my makefile for this c++ application:
CC = g++ -std=c++11
CFLAG = -I/usr/local/Cellar/boost/1.57.0/include
LIBFLAG = -L/usr/local/Cellar/boost/1.57.0/lib
all: client
client: client.o
$(CC) $(LIBFLAG) -lboost_system -lboost_thread client.o -o client
client.o: client.cpp
$(CC) -c $(CFLAG) client.cpp
clean:
rm -rf *.o client
It complains about not finding lboost_thread library after compilation:
ld: library not found for -lboost_thread
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [client] Error 1
In my boost library directory, the boost_thread library shows up like this:
libboost_thread-mt.a libboost_thread-mt.dylib
Why isn't it able to find this library? Did I make any mistake in the linking?
Try changing your makefile to link to -lboost-thread-mt instead of -lboost-thread.
You seems to be missing libboost_thread for some reason
I've been trying to learn spidermonkey and so have written the following code, adapted from this guide and while the program compiles properly, I get the following error during linking:
/usr/bin/ld: cannot open linker script file symverscript: No such file or directory
I'm using 64-bit Ubuntu 13.10, and here is the code (seems irrelevant to the problem, but can't hurt)
#include <jsapi.h>
#include <iostream>
#include <string>
int main()
{
std::string script = "var x = 10;x*x;";
jsval rval;
JSRuntime* runtime = 0;
JSContext* context = 0;
JSObject* globalob = 0;
if((!(runtime = JS_NewRuntime(1024L*1024L, JS_NO_HELPER_THREADS)))||
(!(context = JS_NewContext(runtime, 8192)))||
(!(globalob = JS_NewObject(context, NULL, NULL, NULL))))
{
return 1;
}
if(!JS_InitStandardClasses(context, globalob))
{
return 1;
}
if(!JS_EvaluateScript(context,globalob,script.data(),script.length(),"script",1,&rval))
{
return 1;
}
std::cout << JSVAL_TO_INT(rval) << "\n";
JS_DestroyContext(context);
JS_DestroyRuntime(runtime);
JS_ShutDown();
return 0;
}
compiled with the command
g++ main.cpp -o out $(js24-config --cflags --libs | tr "\n" " ")
Try to write this command instead,
g++ main.cpp -o main -I/usr/local/include/js/ -L/usr/local/lib/ -lmozjs1.8.5
regarding the path I wrote above, you must write your own path which include the library and JSAPI.h file included in,
And the last term is spidermonkey library, you will find it in lib folder, for me it exists in /usr/local/lib