I have an image processing application that uses Qt and openCV.
for each frame, I should send the captured cv::Mat image object to the server to process it and get the results.
I should use the REST architecture for its low playload.
What is the tool that I should use to send cv::Mat to the server.
I am using POCO for portability.
I seek for the lightest solution to do that, I need a minimum speed of 10 frames processed by the server in a second.
I mean, is there a method to pass the C++ Object to the server without an explicit serialization?
EDIT
With the POCO library, you can take a look in this answer: HttpRequest PUT content in poco library. He is sending a file on a ifstream.
In this answer you can check how to convert a cv::Mat into a istream: OpenCV cv::Mat to std::ifstream for base64 encoding.
And finally, Thanks to polymorphism, the istream is implicity converted to a ifstream.
You can use the C++ Rest SDK. A code example of the PUT command.
Source of code
Library Github where you can find the full documentation.
#include <http_client.h>
#include <filestream.h>
#include <iostream>
#include <sstream>
using namespace web::http;
using namespace web::http::client;
// Upload a file to an HTTP server.
pplx::task<void> UploadFileToHttpServerAsync()
{
using concurrency::streams::file_stream;
using concurrency::streams::basic_istream;
// To run this example, you must have a file named myfile.txt in the current folder.
// Alternatively, you can use the following code to create a stream from a text string.
// std::string s("abcdefg");
// auto ss = concurrency::streams::stringstream::open_istream(s);
// Open stream to file.
return file_stream<unsigned char>::open_istream(L"myfile.txt").then([](pplx::task<basic_istream<unsigned char>> previousTask)
{
try
{
auto fileStream = previousTask.get();
// Make HTTP request with the file stream as the body.
http_client client(L"http://www.fourthcoffee.com");
return client.request(methods::PUT, L"myfile", fileStream).then([fileStream](pplx::task<http_response> previousTask)
{
fileStream.close();
std::wostringstream ss;
try
{
auto response = previousTask.get();
ss << L"Server returned returned status code " << response.status_code() << L"." << std::endl;
}
catch (const http_exception& e)
{
ss << e.what() << std::endl;
}
std::wcout << ss.str();
});
}
catch (const std::system_error& e)
{
std::wostringstream ss;
ss << e.what() << std::endl;
std::wcout << ss.str();
// Return an empty task.
return pplx::task_from_result();
}
});
/* Sample output:
The request must be resent
*/
}
I'm trying to access a WebSocket API using the cpprestsdk. The example code I have so far is:
#include <iostream>
#include <cpprest/ws_client.h>
using namespace std;
using namespace web;
using namespace web::websockets::client;
int main() {
websocket_client client;
client.connect("wss://api.poloniex.com").wait();
websocket_outgoing_message out_msg;
out_msg.set_utf8_message("test");
client.send(out_msg).wait();
client.receive().then([](websocket_incoming_message in_msg) {
return in_msg.extract_string();
}).then([](string body) {
cout << body << endl; // test
}).wait();
client.close().wait();
return 0;
}
The page (here) gives the following information:
In order to use the push API, connect to wss://api.poloniex.com and
subscribe to the desired feed [...] In order to receive ticker
updates, subscribe to "ticker".
I can't find out how to subscribe to a channel using this library.
I need to set up an application that listens on a number of Urls but do not know when I start how many - this will eventually be read from a database but for the moment they are hard coded in a demo.
// MultipleListenerTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <string>
#include <vector>
#include <cpprest\http_listener.h>
#include <cpprest\http_client.h>
#include "TestListener.h" // listener object
using namespace web::http::client;
using namespace web::http::experimental::listener;
using namespace web::http;
using namespace web;
void SetListenerArray();
typedef std::vector<http_listener> httpListeners;
listenerCollection listeners;
TestListener listener1;
TestListener Listener2;
TestListener Listener3;
httpListeners httpListenersList;
void handle_get(http_request request);
void handle_post(http_request request);
void handle_put(http_request request);
void handle_del(http_request request);
int _tmain(int argc, _TCHAR* argv[])
{
SetListenerArray();
for each (TestListener tl in listeners)
{
http_listener l(tl.GetUrl());
l.support(methods::GET, handle_get);
l.support(methods::POST, handle_post);
l.support(methods::PUT, handle_put);
l.support(methods::DEL, handle_del);
l.open().wait();
httpListenersList.push_back(l);
}
std::string line;
std::cout << "Press enter to exit" << std::endl;
std::getline(std::cin, line);
//listenerVoices_1.close().wait();
//listenerVoices_2.close().wait();
return 0;
}
void SetListenerArray()
{
// first listener
listener1.SetListenerName(to_string_t("FirstListener"));
listener1.SetUrl(to_string_t("http://localhost:8010"));
listeners.push_back(listener1);
// second listener
Listener2.SetListenerName(to_string_t("Second Listener"));
Listener2.SetUrl(to_string_t("http://localhost:8020"));
listeners.push_back(Listener2);
//third listener
Listener3.SetListenerName(to_string_t("Third Listener"));
Listener3.SetUrl(to_string_t("http://localhost:8030"));
listeners.push_back(Listener3);
}
void handle_get(http_request request)
{
for each (TestListener tl in listeners)
{
std::cout << to_utf8string(tl.GetListenerName());
}
}
void handle_post(http_request request)
{
}
void handle_put(http_request request)
{
}
void handle_del(http_request request)
{
}
With the above code the line
httpListenersList.push_back(l);
fails to compile with the error
Error 1 error C2248: 'web::http::experimental::listener::http_listener::http_listener' : cannot access private member declared in class 'web::http::experimental::listener::http_listener' c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 593 1 MultipleListenerTest
If I leave it out then none of the listeners are actually listening and you get This webpage is not available in Chrome at least.
So how can you set up multiple listeners when you do not know before hand how many are required?
Use threading - each thread executes one of the listeners.
The following is the method in a class which executes a listener.
void Listener::Start()
{
Logger logger;
std::string logMessage("Starting '" + to_utf8string(GetName()) + "' Listener");
http_listener httpListener(GetUri());
std::string listenerName(to_utf8string(name));
logger.log(logMessage);
// listener recieves a GET request.
httpListener.support(methods::GET, [listenerName](http_request request)
{
Logger logger;
std::string logMessage("GET request recieved from " + listenerName);
logger.log(logMessage);
// dummy line just till routing is dealt with
request.reply(status_codes::OK, logMessage);
});
// open listener and route request
httpListener
.open()
.then([&httpListener,listenerName](){
Logger logger;
std::string logMessage(listenerName + " started");
logger.log(logMessage);
}).wait();
// JUST WAIT - we do not want the application to stop
while (true);
}
Then in the program execute the following code which collects all of the listeners in a vector.
Then scans the vectors to create each thread.
RouteMaps rm;
Logger logger;
Listeners ls;
std::vector<std::thread> listener_threads;
std::vector<Listener> lvector;
std::cout.sync_with_stdio(true);
// collect all the listeners into a vector
for (auto& m : rm.Select()) {
for (auto& l : ls.Select(m.GetId())) {
std::string logMessage("Retrieved Listener " + to_utf8string(l.GetName()));
logger.log(logMessage);
lvector.push_back(l);
}
}
std::cout << "Starting listeners" << std::endl;
// now create threads for each listener
for (auto& lstnr : lvector)
{
listener_threads.push_back(std::thread{ &Listener::Start, &lstnr });
}
The application will however drop through and end - stopping each thread. Now at the bottom of each thread there is a permanent loop - that means no thread will actually end.
To stop the program execution killing each thread they need to be joined to the main thread with the following loop.
for (auto& t : listener_threads)
{
t.join();
}
In this way we now have a number of threads and you do not have to define in code how many.
Now when I place the domain of each listener in a browser we get a reply from each one.
I'm wondering how I can do a request to a URL (e.g. download a picture and save it) with POCO in C++?
I got this little code so far
#include <iostream>
#include <string>
#include "multiplication.h"
#include <vector>
#include <HTTPRequest.h>
using std::cout;
using std::cin;
using std::getline;
using namespace Poco;
using namespace Net;
int main() {
HTTPRequest *test = new HTTPRequest("HTTP_GET", "http://www.example.com", "HTTP/1.1");
}
Normally POCO has a great advantage to be very simple even when you know nothing about it and you do not need middle/advance C++ knowledge like you need for boost/asio ( e.g what means enable_share_from_this ... )
Under the poco "installation directory" you find the sample directory, (in my case under poco\poco-1.4.6p4\Net\samples\httpget\src ).
On-line help browsing is also easy and fast (for example browsing classes).
If your understanding of C++ in not enough at the present time go to the university library and borrow Scott Meyers books (Effective C++ and after More effective C++ )
So we adapt the sample code httpget.cpp to the minimal required.
Inside the main:
URI uri("http://pocoproject.org/images/front_banner.jpg");
std::string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
HTTPClientSession session(uri.getHost(), uri.getPort());
HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
HTTPResponse response;
if (!doRequest(session, request, response))
{
std::cerr << "Invalid username or password" << std::endl;
return 1;
}
and the function almost untouched:
bool doRequest(Poco::Net::HTTPClientSession& session,
Poco::Net::HTTPRequest& request,
Poco::Net::HTTPResponse& response)
{
session.sendRequest(request);
std::istream& rs = session.receiveResponse(response);
std::cout << response.getStatus() << " " << response.getReason() << std::endl;
if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
{
std::ofstream ofs("Poco_banner.jpg",std::fstream::binary);
StreamCopier::copyStream(rs, ofs);
return true;
}
else
{
//it went wrong ?
return false;
}
}
I let you arrange things for you and see where the image lands on your disk.
Hope it will help
I came across an embedded web server named mongoose and http://code.google.com/p/mongoose/ and I read the wiki it was great and i searched for some sample hello world program but i couldn't find it... i found some example but that was written in c++ for windows and can any one provide an example c program to run this webserver..
It is quite simple, first you need to implement the call back function:
void *event_handler(enum mg_event event,
struct mg_connection *conn) {
const struct mg_request_info *request_info = mg_get_request_info(conn);
static void* done = "done";
if (event == MG_NEW_REQUEST) {
if (strcmp(request_info->uri, "/hello") == 0) {
// handle c[renderer] request
if(strcmp(request_info->request_method, "GET") != 0) {
// send error (we only care about HTTP GET)
mg_printf(conn, "HTTP/1.1 %d Error (%s)\r\n\r\n%s",
500,
"we only care about HTTP GET",
"we only care about HTTP GET");
// return not null means we handled the request
return done;
}
// handle your GET request to /hello
char* content = "Hello World!";
char* mimeType = "text/plain";
int contentLength = strlen(content);
mg_printf(conn,
"HTTP/1.1 200 OK\r\n"
"Cache: no-cache\r\n"
"Content-Type: %s\r\n"
"Content-Length: %d\r\n"
"\r\n",
mimeType,
contentLength);
mg_write(conn, content, contentLength);
return done;
}
}
// in this example i only handle /hello
mg_printf(conn, "HTTP/1.1 %d Error (%s)\r\n\r\n%s",
500, /* This the error code you want to send back*/
"Invalid Request.",
"Invalid Request.");
return done;
}
// No suitable handler found, mark as not processed. Mongoose will
// try to serve the request.
return NULL;
}
Then you need to start the server:
int main(int argc, char **argv) {
/* Default options for the HTTP server */
const char *options[] = {
"listening_ports", "8081",
"num_threads", "10",
NULL
};
/* Initialize HTTP layer */
static struct mg_context *ctx;
ctx = mg_start(&event_handler, options);
if(ctx == NULL) {
exit(EXIT_FAILURE);
}
puts("Server running, press enter to exit\n");
getchar();
mg_stop(ctx);
return EXIT_SUCCESS;
}
I wrote a C++ REST service library that uses Mongoose. Here's a simple example:
#include <iostream>
#include <server/server.hpp>
int main()
{
using namespace pwned::server;
Server server;
server.Get("/", [](mg_event*, Params const &) {
return Server::response("Hello!");
});
std::cin.get();
}
Based on
https://github.com/nurettin/pwned/blob/master/examples/server/basics/server.cpp
Compile application: $ cc my_app.c mongoose.c
#include "mongoose.h" // Include Mongoose API definitions
static const char *s_http_port = "8089";
// Define an event handler function
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data)
{
struct mbuf *io = &nc->recv_mbuf;
switch (ev)
{
case MG_EV_RECV:
// This event handler implements simple TCP echo server
mg_send(nc, io->buf, io->len); // Echo received data back
mbuf_remove(io, io->len); // Discard data from recv buffer
break;
default:
break;
}
}
int main(void)
{
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL); // Initialize event manager object
// Note that many connections can be added to a single event manager
// Connections can be created at any point, e.g. in event handler function
mg_bind(&mgr, s_http_port, ev_handler); // Create listening connection and add it to the event manager
for (;;)
{
// Start infinite event loop
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
For anyone looking at this thread - from the mongoose library author (me).
Mongoose web server has long ago moved to https://github.com/cesanta/mongoose
It has a comprehensive list of examples, starting from a simplest ones, to the more complex ones, see examples directory in the repository. The minimal static HTTP server goes as follows:
#include "mongoose.h"
static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve local dir
if (ev == MG_EV_HTTP_MSG) mg_http_serve_dir(c, ev_data, &opts);
}
int main(int argc, char *argv[]) {
struct mg_mgr mgr;
mg_mgr_init(&mgr); // Init manager
mg_http_listen(&mgr, "http://localhost:8000", fn, &mgr); // Setup listener
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
mg_mgr_free(&mgr); // Cleanup
return 0;
}