Add HTTP Services into C++ Programs Using PION-NET

In the recent four years, I have been working on parallel machine learning systems, where a learning job consists of multiple processes running in parallel on many computers.  These processes may run for a long time (from dozens of minutes up to several days), thus I often like to monitor their status like statistics (e.g., CPU and memory heap consumptions) and progress (how many data it has processed).  Logging can expose status, but usually not in a comprehensive way.  A more elegant solution is to make each process spawn a thread to run a Web service, which exposes the status in the format of HTML.

After a weeks-long survey, I decided to use pion-net, a library built upon Boost::Asio.  A blog post here explains some advantages of Boost::Asio. The building and installation of pion-net is straight-forward; just ./configure && make && make install. If you want to use your own builds of boost and openssl, use ./configure --with-openssl=openssl-prefix-dir --with-boost=boost-prefix-dir.

In the source directory /pion-net-3.0.15/net/utils/ of pion-net, there are examples showing how to use pion::net::TCPServer and pion::net::WebServer. Here follows an additional example for pion::net::HTTPServer:

// Copyright (C) 2010  Yi Wang (
// Demonstrate how to add HTTP service into a Boost/C++ program.

#include <iostream>
#include <pion/net/HTTPServer.hpp>
#include <pion/net/HTTPTypes.hpp>
#include <pion/net/HTTPRequest.hpp>
#include <pion/net/HTTPResponseWriter.hpp>

using namespace std;
using namespace pion;
using namespace pion::net;

void handleRootURI(HTTPRequestPtr& http_request, TCPConnectionPtr& tcp_conn) {
  static const std::string kHTMLStart("<html><body>\n");
  static const std::string kHTMLEnd("</body></html>\n");

  HTTPResponse& r = writer->getResponse();

  HTTPTypes::QueryParams& params = http_request->getQueryParams();

  writer->write("The query about resource ");

  if (params.size() > 0) {
    writer->write(" has the following parameters: <br>");
    for (HTTPTypes::QueryParams::const_iterator i = params.begin();
         i != params.end(); ++i) {
  } else {
    writer->write(" has no parameter.");

int main (int argc, char *argv[]) {
  static const unsigned int DEFAULT_PORT = 8080;
  try {
    HTTPServerPtr hello_server(new HTTPServer(DEFAULT_PORT));
    hello_server->addResource("/", &handleRootURI);
    hello_server->start();      // Spawn a thead to run the HTTP
                                // service, and the main thread can
                                // focus on the main work now.
    std::cout << "Hello, the server is running now ...\n";
  } catch (std::exception& e) {
    std::cerr << "Failed running the HTTP service due to " <<  e.what();
  return 0;

The following Makefile lists libraries required to build this program:

pion_hello_service :
 g++ \
 -I/Users/wangyi/3rd-party/pion-net-3.0.15/include \
 -I/Users/wangyi/3rd-party/boost-1.43.0/include \
 -I/Users/wangyi/3rd-party/openssl-0.9.8o/include \ \
 -L/Users/wangyi/3rd-party/pion-net-3.0.15/lib \
 -L/Users/wangyi/3rd-party/boost-1.43.0/lib \
 -L/Users/wangyi/3rd-party/openssl-0.9.8o/lib \
 -lpion-common -lpion-net \
 -lboost_thread -lboost_system -lboost_filesystem -lboost_regex \
 -lboost_date_time -lboost_signals -lboost_iostreams \
 -lssl -lcrypto -lz -lbz2 -ldl