I have to write a function in c++ which calls shared library which is created from gRPC client which runs the gRPC client and returns the result.
Is there any samples?
Here are Some Examples I hope i would be helpful somehow.
#include <iostream>
#include <memory>
#include <string>
#include <grpcpp/grpcpp.h>
#ifdef BAZEL_BUILD
#include "examples/protos/helloworld.grpc.pb.h"
#else
#include "helloworld.grpc.pb.h"
#endif
using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;
using helloworld::HelloRequest;
using helloworld::HelloReply;
using helloworld::Greeter;
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.message();
}
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)
{
// Instantiate the client. It requires a channel, out of which the actual RPCs are created. This channel models a connection to an endpoint (in this case, localhost at port 50051). We indicate that the channel isn't authenticated (use of InsecureChannelCredentials()).
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 0;
}
OR
#include <iostream>
#include <string>
#include <dlfcn.h > // for dlopen, dlsym, dlclose
using namespace std;
int main()
{
void *handle; // handle to the library
string(*func)(string); // function pointer
char *error; // error message
handle = dlopen("/home/user/Desktop/grpc_client/libgrpc_client.so", RTLD_NOW); // open the library
if (!handle)
{
fputs(dlerror(), stderr); // print error message
exit(1);
}
func = (string(*)(string)) dlsym(handle, "run_grpc_client"); // get the function pointer
if ((error = dlerror()) != NULL)
{
fputs(error, stderr); // print error message
exit(1);
}
string result = func("hello"); // call the function
cout << result << endl;
dlclose(handle); // close the library
return 0;
}
Related
I am working on an cpp MQTT async_client utilizing the paho library. I am trying to fully understand the workings of the asynchronous client, but I am not sure how to correctly utilize the features.
As I understand it, messages with QoS > 0 follow a handshake procedure specified by the standard. The delivery to the server is regarded as complete if either PUBACK (QoS 1) or PUBCOMP (QoS 2) has been received. All of this seems to be handled by the library. The user can interact with the client either through callbacks or through tokens associated with specific actions (e.g. publish).
I have the following questions regarding these tools:
The user can either register a mqtt::iaction_listener callback to an action that is invoked when the action fails and/or succeeds. Simultaneously, there exists a callback when the last message of a handshake has been successfully received (PUBACK and PUBCOMP, respectively). Are the success callbacks not redundant?
Waiting for message tokens to complete in an asynchronous client does not make sense for me. If I wait for message to be published, I block the sending thread. Surely, I could use separate thread for waiting, but that defeats the purpose of asynchronous clients. So do I just omit the wait, especially when sending messages in rapid succession? (see code below)
Test client code:
#include <iostream>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cctype>
#include <thread>
#include <chrono>
#include "mqtt/async_client.h"
const std::string SERVER_ADDRESS("tcp://localhost:1883");
const std::string CLIENT_ID("client1");
const std::string TOPIC("hello");
class Callback
: public virtual mqtt::callback
{
// the mqtt client
mqtt::async_client& cli_;
void delivery_complete(mqtt::delivery_token_ptr tok) override
{
std::cout << "delivery_complete for token: " << tok->get_message_id() << std::endl;
}
public:
Callback(mqtt::async_client& cli)
: cli_(cli) {}
};
int main(int argc, char* argv[])
{
mqtt::async_client cli(SERVER_ADDRESS, CLIENT_ID);
mqtt::connect_options connOpts;
connOpts.set_clean_session(false);
Callback cb(cli);
cli.set_callback(cb);
// Connect; waiting makes sense here as publishing without a connection is nonsense
try {
cli.connect(connOpts);
}
catch (const mqtt::exception& exc) {
std::cerr << "\nERROR: Unable to connect to MQTT server: '"
<< SERVER_ADDRESS << "'" << exc << std::endl;
return 1;
}
// Press 'm' to send messages or 'q' to exit
while (true)
{
char c = std::tolower(std::cin.get());
if (c == 'q') {
break;
}
else if (c == 'm')
{
for (int i = 0; i < 10; ++i)
{
mqtt::message_ptr pubmsg = mqtt::make_message(TOPIC, "TESTMSG");
pubmsg->set_qos(1);
auto tok = cli.publish(pubmsg);
tok->wait(); // how is this done correctly with QoS > 0 ?
}
}
}
// Disconnect
try {
cli.disconnect()->wait();
std::cout << "OK" << std::endl;
}
catch (const mqtt::exception& exc) {
std::cerr << exc << std::endl;
return 1;
}
return 0;
}
I am trying to decompress message returning from WebSocket API(Okex). I tried to use zlib to decompress but fails. Please advise how to do so.
The following are websocket class written to connect to okex and returning data from the websocket server.
#include <websocketpp/config/asio_client.hpp>
#include <websocketpp/client.hpp>
#include <iostream>
typedef websocketpp::client<websocketpp::config::asio_tls_client> client;
typedef std::shared_ptr<boost::asio::ssl::context> context_ptr;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef websocketpp::config::asio_client::message_type::ptr message_ptr;
using websocketpp::lib::bind;
void on_open(client* c, websocketpp::connection_hdl hdl) {
std::string msg = "{\"op\": \"subscribe\", \"args\": [\"spot/depth5:ETH-USDT\"]}";
c->send(hdl,msg,websocketpp::frame::opcode::text);
c->get_alog().write(websocketpp::log::alevel::app, "Sent Message: "+msg);
}
void websocketClient::on_message(websocketpp::connection_hdl hdl, message_ptr msg) {
std::cout << msg->get_payload().size()<< std::endl;
std::cout << msg->get_payload().data()<< std::endl;
string str = utility::inflationAlgorithm::decompress(msg->get_payload());
}
websocketClient::websocketClient() {
client c;
std::string uri = "wss://real.okex.com:8443/ws/v3";
try {
// Set logging to be pretty verbose (everything except message payloads)
c.set_access_channels(websocketpp::log::alevel::all);
c.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize ASIO
c.init_asio();
c.set_tls_init_handler(bind(&on_tls_init));
// Register our message handler
c.set_open_handler(bind(&on_open, &c,::_1));
c.set_message_handler(bind(&websocketClient::on_message,this,::_1,::_2));
websocketpp::lib::error_code ec;
websocketClient::con = c.get_connection(uri, ec);
if (ec) {
std::cout << "could not create connection because: " << ec.message() << std::endl;
}else {
c.connect(websocketClient::con);
// Start the ASIO io_service run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
}
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
}
}
The following code are written to decompress the message returning from Okex, but unable to get decompressed string.
#include <sstream>
#include "inflationAlgorithm.h"
using namespace zlibcomplete;
using namespace std;
std::string utility::inflationAlgorithm::decompress(const std::string & str)
{
z_stream zs; // z_stream is zlib's control structure
memset(&zs, 0, sizeof(zs));
if (inflateInit2(&zs, 47) != Z_OK)
throw(std::runtime_error("inflateInit failed while decompressing."));
zs.next_in = (Bytef*)str.data();
zs.avail_in = (uint)str.size();
int ret;
char outbuffer[32768];
std::string outstring;
// get the decompressed bytes blockwise using repeated calls to inflate
do {
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = inflateInit2(&zs, 47);
if (outstring.size() < zs.total_out) {
outstring.append(outbuffer,
zs.total_out - outstring.size());
}
} while (ret == Z_OK);
inflateEnd(&zs);
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
std::ostringstream oss;
oss << "Exception during zlib decompression: (" << ret << ") "
<< zs.msg;
throw(std::runtime_error(oss.str()));
}
return outstring;
}
I'm working on a packet-capturing program.
I started from one of libtins examples on http http://libtins.github.io/examples/http-requests/.
but VS prompts a
C2664
Error C2664 'bool main::::operator ()(Tins::Packet &) const': cannot convert argument 1 from 'Tins::PDU' to 'Tins::Packet &' packetSniff path-to-tins\sniffer.h 681
on the following part of the sniffer.h
try {
// If the functor returns false, we're done
#if TINS_IS_CXX11 && !defined(_MSC_VER)
if (!Tins::Internals::invoke_loop_cb(function, *it)) {
return;
}
//here
#else
if (!function(*it->pdu())) {
return;
}
#endif
}
I have already build and run the example from the front page
http://libtins.github.io/
But the following code produces C2664
#define WIN32
#define TINS_STATIC
#define NOMINMAX
#pragma warning(disable : 4996)
#include <string>
#include <iostream>
#include <stdexcept>
#include <boost/regex.hpp>
#include <tins/tcp_ip/stream_follower.h>
#include <tins/sniffer.h>
#include <tins/tins.h>
#include "color.h"
#include <vector>
#include <sstream>
using std::string;
using std::cout;
using std::cerr;
using std::endl;
using std::exception;
using std::vector;
using std::wcout;
using std::stringstream;
using boost::regex;
using boost::match_results;
using Tins::Packet;
using Tins::Sniffer;
using Tins::SnifferConfiguration;
using Tins::TCPIP::Stream;
using Tins::TCPIP::StreamFollower;
using Tins::NetworkInterface;
using termcolor::on_red;
using termcolor::on_green;
using termcolor::reset;
// This example captures and follows TCP streams seen on port 80. It will
// wait until both the client and server send data and then apply a regex
// to both payloads, extrating some information and printing it.
// Don't buffer more than 3kb of data in either request/response
const size_t MAX_PAYLOAD = 3 * 1024;
// The regex to be applied on the request. This will extract the HTTP
// method being used, the request's path and the Host header value.
regex request_regex("([\\w]+) ([^ ]+).+\r\nHost: ([\\d\\w\\.-]+)\r\n");
// The regex to be applied on the response. This finds the response code.
regex response_regex("HTTP/[^ ]+ ([\\d]+)");
void on_server_data(Stream& stream) {
match_results<Stream::payload_type::const_iterator> client_match;
match_results<Stream::payload_type::const_iterator> server_match;
const Stream::payload_type& client_payload = stream.client_payload();
const Stream::payload_type& server_payload = stream.server_payload();
// Run the regexes on client/server payloads
bool valid = regex_search(server_payload.begin(), server_payload.end(),
server_match, response_regex) &&
regex_search(client_payload.begin(), client_payload.end(),
client_match, request_regex);
stringstream ss;
for (char c : server_payload) {
ss << c;
}
cout << on_green << "Server raw payload " <<
ss.str() << reset << endl;
// If we matched both the client and the server regexes
if (valid) {
// Extract all fields
string method = string(client_match[1].first, client_match[1].second);
string url = string(client_match[2].first, client_match[2].second);
string host = string(client_match[3].first, client_match[3].second);
string response_code = string(server_match[1].first, server_match[1].second);
// Now print them
cout << method << " http://" << host << url << " -> " << response_code << endl;
// Once we've seen the first request on this stream, ignore it
stream.ignore_client_data();
stream.ignore_server_data();
}
// Just in case the server returns invalid data, stop at 3kb
if (stream.server_payload().size() > MAX_PAYLOAD) {
stream.ignore_server_data();
}
}
void on_client_data(Stream& stream) {
// Don't hold more than 3kb of data from the client's flow
if (stream.client_payload().size() > MAX_PAYLOAD) {
stream.ignore_client_data();
}
}
void on_new_connection(Stream& stream) {
stream.client_data_callback(&on_client_data);
stream.server_data_callback(&on_server_data);
// Don't automatically cleanup the stream's data, as we'll manage
// the buffer ourselves and let it grow until we see a full request
// and response
stream.auto_cleanup_payloads(false);
}
int main(int argc, char* argv[]) {
// First fetch all network interfaces
vector<NetworkInterface> interfaces = NetworkInterface::all();
// Now iterate them
int i = 0;
for (const NetworkInterface& iface : interfaces) {
// First print the name (GUID)
cout << i++ << ' ' << "Interface name: " << termcolor::on_red << iface.name() <<
termcolor::on_cyan << ' ' << iface.addresses().ip_addr << termcolor::reset;
// Now print the friendly name, a wstring that will contain something like
// "Local Area Connection 2"
wcout << " (" << iface.friendly_name() << ")" << endl;
}
try {
// Construct the sniffer configuration object
SnifferConfiguration config;
// Only capture TCP traffic sent from/to port 80
config.set_filter("tcp port 5000");
// Construct the sniffer we'll use
Sniffer sniffer(interfaces[5].name(), config);
wcout << on_green <<"Starting capture on interface " <<
interfaces[5].friendly_name() << reset << endl;
// Now construct the stream follower
StreamFollower follower;
// We just need to specify the callback to be executed when a new
// stream is captured. In this stream, you should define which callbacks
// will be executed whenever new data is sent on that stream
// (see on_new_connection)
follower.new_stream_callback(&on_new_connection);
// Now start capturing. Every time there's a new packet, call
// follower.process_packet
sniffer.sniff_loop([&](Packet& packet) {
follower.process_packet(packet);
return true;
});
}
catch (exception& ex) {
cerr << "Error: " << ex.what() << endl;
return 1;
}
}
According to the code inside sniffer.h,
try {
// If the functor returns false, we're done
#if TINS_IS_CXX11 && !defined(_MSC_VER)
if (!Tins::Internals::invoke_loop_cb(function, *it)) {
return;
}
//here
#else
if (!function(*it->pdu())) {
return;
}
#endif
}
When you uses VS to compile, the macro _MSC_VER is defined by default, and your code will go to the #else branch, so it will call your callback with a PDU object. To avoid that I would suggest you to choose a different compiler or look for their instructions specifically for MSVC.
I finally came across a work around by casting it to Tins::Packet & in sniffer.h
if (!function((Tins::Packet &)*it->pdu())) {
return;
}
I am new to Streams and Buffers implementation and I do not really know how to fix this:
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>
#include <thread>
#include <boost/property_tree/json_parser.hpp>
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
using tcp = boost::asio::ip::tcp;
namespace websocket = boost::beast::websocket;
namespace pt = boost::property_tree;
struct DefaultMessage {
std::string command;
int value;
};
void defaultMessage(DefaultMessage *dm ,pt::ptree *root) {
root->put("command", dm->command);
root->put("value", dm->value);
}
// Echoes back all received WebSocket messages
void do_session(tcp::socket &socket) {
try {
// Construct the stream by moving in the socket
websocket::stream<tcp::socket> ws{std::move(socket)};
// Accept the websocket handshake
ws.accept();
for (;;) {
// Read a message into the buffer
boost::beast::multi_buffer buffer;
ws.read(buffer);
// Make string from buffer
auto s = boost::beast::buffers_to_string(buffer.data());
// Create ptree root
pt::ptree root;
// Create array source from s
boost::iostreams::array_source array_source(&s[0], s.size());
// Create input stream from array source
boost::iostreams::stream<boost::iostreams::array_source> input_stream(array_source);
// Read the json an populate ptree root
pt::read_json(input_stream, root);
// Discard all in buffer
buffer.consume(buffer.size());
// Construct a default message
auto message = DefaultMessage{
root.get<std::string>("command"),
root.get<int>("value")
};
defaultMessage(&message, &root);
// **This won't compile.**
pt::write_json(buffer, root);
// Echo the message back
ws.text(ws.got_text());
ws.write(buffer.data());
}
}
catch (boost::system::system_error const &se) {
// This indicates that the session was closed
if (se.code() != websocket::error::closed) {
std::cerr << "Error: " << se.code().message() << std::endl;
}
}
catch (std::exception const &e) {
std::cerr << "Error: " << e.what() << std::endl;
}
}
I want to respond with the message struct. So I guess I need to put it back in the buffer. This part is what is do not know how to do.
If efficiency is not your top concern, I'd suggest
std::ostringstream oss;
pt::write_json(oss, root);
to write to a string, and
// Echo the message back
ws.text(ws.got_text());
ws.write(boost::asio::buffer(oss.str()));
to write that buffer out.
Caveats:
this does more allocations than strictly required, probably
Boost PropertyTree is NOT a JSON library
when i build my own cpprestsdk server and client,i found that when my server receive a request and reply to it, my client have no reaction to it,and it never goes into the breakpoint where i handle the http_response,here is my code;
i was stuck for so many days,will someone help me fix this,thanks a lot
(client send request,server receives it and reply, client fail to receive http_response)
Server(i just got it from somewhere on internet):
#include "cpprest/json.h"
#include "cpprest/http_listener.h"
#include "cpprest/uri.h"
#include "cpprest/asyncrt_utils.h"
#include "cpprest/http_client.h"
using namespace web::http::experimental::listener;
using namespace web::http;
using namespace web;
void handle_get(http_request message)
{
message.reply(status_codes::OK, U("Hello, World!"));
};
void handle_post(http_request message)
{
message.reply(status_codes::NotFound);
};
void handle_put(http_request message)
{
message.reply(status_codes::NotFound);
};
void handle_delete(http_request message)
{
message.reply(status_codes::NotFound);
};
#define TRACE(msg) std::wcout << msg
#define TRACE_ACTION(a, k, v) std::wcout << a << L" (" << k << L", " << v << L")\n"
int main(int argc, char ** argv)
{
uri_builder uri(U("http://localhost:8888"));
http_listener listener(uri.to_uri());
listener.support(methods::GET, handle_get);
listener.support(methods::POST, handle_post);
listener.support(methods::PUT, handle_put);
listener.support(methods::DEL, handle_delete);
try
{
listener
.open()
.then([&listener](){TRACE(L"\nstarting to listen\n"); })
.wait();
while (true);
}
catch (std::exception const & e)
{
std::wcout << e.what() << std::endl;
}
catch (...)
{
std::wcout << "Unknown exception" << std::endl;
}
return 0;
}
and here is my Client
#include "cpprest/http_client.h"
#include "cpprest/filestream.h"
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
int main(int argc, char* argv[])
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://www.bing.com/"));
http_client localclient(U("http://localhost:8888"));
return localclient.request(methods::GET);
})
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
system("pause");
return response.body().read_to_end(fileStream->streambuf());
})
.then([=](size_t)
{
return fileStream->close();
});
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
system("pause");
}
return 0;
}