Compiling poco and httpserver and tcpserver on Windows 10

Time:2019-12-2

This article starts from my blog https://kezunlin.me/post/9587bb47/, welcome to read!

compile and install poco cpp library on windows

Series

  • guide to compile and install poco cpp library on windows
  • guide to compile and install poco cpp library on ubuntu 16.04

Guide

download

wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.zip
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.tar.gz

build

build options

buildwin.cmd

    rem Usage:
    rem ------
    rem buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL]
    rem VS_VERSION:    90|100|110|120|140|150
    rem ACTION:        build|rebuild|clean
    rem LINKMODE:      static_mt|static_md|shared|all
    rem CONFIGURATION: release|debug|both
    rem PLATFORM:      Win32|x64|WinCE|WEC2013
    rem SAMPLES:       samples|nosamples
    rem TESTS:         tests|notests
    rem TOOL:          devenv|vcexpress|wdexpress|msbuild

we choose to build with visual studio 2015

build_vs140.cmd

    @echo off
    buildwin 140 build shared release x64 samples

build

./build_vs140.cmd

or

cmake-gui ..

cmake-gui and open sln to build with release x64and install to C:/Program Files/Poco so that find_package(Poco REQURIED) take effect.

$ ls Poco

bin  include  lib

$ ll Poco/lib

total 3.5M
drwxr-xr-x 1 zunli zunli     0 Jan 25 07:39 cmake
-rw-r--r-- 1 zunli zunli  1.5M Jan 25 06:59 PocoFoundation.lib
-rw-r--r-- 1 zunli zunli  111K Jan 25 06:59 PocoJSON.lib
-rw-r--r-- 1 zunli zunli 1007K Jan 25 07:00 PocoNet.lib
-rw-r--r-- 1 zunli zunli  320K Jan 25 07:00 PocoUtil.lib
-rw-r--r-- 1 zunli zunli  595K Jan 25 07:00 PocoXML.lib

Poco Example

CMakeLists.txt

cmake_minimum_required (VERSION 2.6)

project (event_demo)
enable_language(C)
enable_language(CXX)

# Always include the source and build directories in the include path.
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON)

# no Poco_INCLUDE_DIRS, we have to set by hand 
if(MSVC) # WIN32
    SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include")
else()
    SET(Poco_INCLUDE_DIRS "/usr/local/include/Poco")
endif(MSVC)

MESSAGE( [Main] " Poco_INCLUDE_DIRS = ${Poco_INCLUDE_DIRS}")
MESSAGE( [Main] " Poco_LIBRARIES = ${Poco_LIBRARIES}")

# The following folder will be included
include_directories(
    ${MY_SRC_INCLUDE}  
    ${Poco_INCLUDE_DIRS} 
    )   

link_directories(${CMAKE_BINARY_DIR}) 

add_executable(event_demo event_demo.cpp)
target_link_libraries(event_demo ${Poco_LIBRARIES})

Notice 1: find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON) and use ${Poco_INCLUDE_DIRS}, ${Poco_LIBRARIES}.

Notice 2: we have to set SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include") by hand.

event

event_demo.cpp

#include "Poco/BasicEvent.h"
#include "Poco/Delegate.h"
#include <iostream>

using Poco::BasicEvent;
using Poco::Delegate;

class Source
{
public:
    BasicEvent<int> theEvent;

    void fireEvent(int n)
    {
        theEvent(this, n);
    }
};

class Target
{
public:
    void onEvent(const void* pSender, int& arg)
    {
        std::cout << "onEvent: " << arg << std::endl;
    }
};

int main(int argc, char** argv)
{
    Source source;
    Target target;

    source.theEvent += Delegate<Target, int>(
        &target, &Target::onEvent);

    source.fireEvent(42);

    source.theEvent -= Delegate<Target, int>(
        &target, &Target::onEvent);

    return 0;
}

active method

#include "Poco/ActiveMethod.h"
#include "Poco/ActiveResult.h"
#include <utility>
#include <iostream>

using Poco::ActiveMethod;
using Poco::ActiveResult;

class ActiveAdder
{
public:
    ActiveAdder() : add(this, &ActiveAdder::addImpl)
    {
    }

    ActiveMethod<int, std::pair<int, int>, ActiveAdder> add;

private:
    int addImpl(const std::pair<int, int>& args)
    {
        return args.first + args.second;
    }
};

int main(int argc, char** argv)
{
    ActiveAdder adder;

    ActiveResult<int> sum = adder.add(std::make_pair(1, 2));
    // do other things
    sum.wait();
    std::cout << sum.data() << std::endl;

    return 0;
}

http server

#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/ThreadPool.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>

using Poco::Net::ServerSocket;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::ThreadPool;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::OptionCallback;
using Poco::Util::HelpFormatter;

class TimeRequestHandler : public HTTPRequestHandler
{
public:
    TimeRequestHandler(const std::string& format) : _format(format)
    {
    }

    void handleRequest(HTTPServerRequest& request,
        HTTPServerResponse& response)
    {
        Application& app = Application::instance();
        app.logger().information("[LOG] Request from "
            + request.clientAddress().toString());

        Timestamp now;
        std::string dt(DateTimeFormatter::format(now, _format));

        response.setChunkedTransferEncoding(true);
        response.setContentType("text/html");

        std::ostream& ostr = response.send();
        ostr << "<html><head><title>HTTPTimeServer powered by "
            "POCO C++ Libraries</title>";
        ostr << "<meta http-equiv=\"refresh\" content=\"1\"></head>";
        ostr << "<body><p style=\"text-align: center; "
            "font-size: 48px;\">";
        ostr << dt;
        ostr << "</p></body></html>";
    }

private:
    std::string _format;
};

class TimeRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
    TimeRequestHandlerFactory(const std::string& format) :
        _format(format)
    {
    }

    HTTPRequestHandler* createRequestHandler(
        const HTTPServerRequest& request)
    {
        if (request.getURI() == "/")
            return new TimeRequestHandler(_format);
        else
            return 0;
    }

private:
    std::string _format;
};

class HTTPTimeServer : public Poco::Util::ServerApplication
{
public:
    HTTPTimeServer() : _helpRequested(false)
    {
    }

    ~HTTPTimeServer()
    {
    }

protected:
    void initialize(Application& self)
    {
        Application& app = Application::instance();
        app.logger().information("[HTTPTimeServer] initialize port=9980 ");

        loadConfiguration();
        ServerApplication::initialize(self);
    }

    void uninitialize()
    {
        Application& app = Application::instance();
        app.logger().information("[HTTPTimeServer] uninitialize ");

        ServerApplication::uninitialize();
    }

    void defineOptions(OptionSet& options)
    {
        ServerApplication::defineOptions(options);

        options.addOption(
            Option("help", "h", "display argument help information")
            .required(false)
            .repeatable(false)
            .callback(OptionCallback<HTTPTimeServer>(
                this, &HTTPTimeServer::handleHelp)));
    }

    void handleHelp(const std::string& name,
        const std::string& value)
    {
        HelpFormatter helpFormatter(options());
        helpFormatter.setCommand(commandName());
        helpFormatter.setUsage("OPTIONS");
        helpFormatter.setHeader(
            "A web server that serves the current date and time.");
        helpFormatter.format(std::cout);
        stopOptionsProcessing();
        _helpRequested = true;
    }

    int main(const std::vector<std::string>& args)
    {
        Application& app = Application::instance();
        app.logger().information("[HTTPTimeServer] main ");

        if (!_helpRequested)
        {
            unsigned short port = (unsigned short)
                config().getInt("HTTPTimeServer.port", 9980);
            std::string format(
                config().getString("HTTPTimeServer.format",
                    DateTimeFormat::SORTABLE_FORMAT));

            ServerSocket svs(port);
            HTTPServer srv(new TimeRequestHandlerFactory(format),
                svs, new HTTPServerParams);
            srv.start();
            waitForTerminationRequest();
            srv.stop();
        }
        return Application::EXIT_OK;
    }

private:
    bool _helpRequested;
};

int main(int argc, char** argv)
{
    HTTPTimeServer app;
    return app.run(argc, argv);
    //visit http://localhost:9980
}

tcp server/client

tcpserver

//
// TimeServer.cpp
//
// This sample demonstrates the TCPServer and ServerSocket classes.
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier:    BSL-1.0
//


#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>


using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServer;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;


class TimeServerConnection : public TCPServerConnection
    /// This class handles all client connections.
    ///
    /// A string with the current date and time is sent back to the client.
{
public:
    TimeServerConnection(const StreamSocket& s, const std::string& format) :
        TCPServerConnection(s),
        _format(format)
    {
    }

    void run()
    {
        Application& app = Application::instance();
        app.logger().information("Request from " + this->socket().peerAddress().toString());
        try
        {
            Timestamp now;
            //std::string dt(DateTimeFormatter::format(now, _format));
            //dt.append("\r\n");
            std::string dt("hello world");
            std::string info("sending:  [" + dt + "] with length="+std::to_string(dt.length()) );
            app.logger().information(info);
            socket().sendBytes(dt.data(), (int)dt.length());
        }
        catch (Poco::Exception& exc)
        {
            app.logger().log(exc);
        }
    }

private:
    std::string _format;
};


class TimeServerConnectionFactory : public TCPServerConnectionFactory
    /// A factory for TimeServerConnection.
{
public:
    TimeServerConnectionFactory(const std::string& format) :
        _format(format)
    {
    }

    TCPServerConnection* createConnection(const StreamSocket& socket)
    {
        return new TimeServerConnection(socket, _format);
    }

private:
    std::string _format;
};


class TimeServer : public Poco::Util::ServerApplication
    /// The main application class.
    ///
    /// This class handles command-line arguments and
    /// configuration files.
    /// Start the TimeServer executable with the help
    /// option (/help on Windows, --help on Unix) for
    /// the available command line options.
    ///
    /// To use the sample configuration file (TimeServer.properties),
    /// copy the file to the directory where the TimeServer executable
    /// resides. If you start the debug version of the TimeServer
    /// (TimeServerd[.exe]), you must also create a copy of the configuration
    /// file named TimeServerd.properties. In the configuration file, you
    /// can specify the port on which the server is listening (default
    /// 9911) and the format of the date/time string sent back to the client.
    ///
    /// To test the TimeServer you can use any telnet client (telnet localhost 9911).
{
public:
    TimeServer() : _helpRequested(false)
    {
    }

    ~TimeServer()
    {
    }

protected:
    void initialize(Application& self)
    {
        loadConfiguration(); // load default configuration files, if present
        ServerApplication::initialize(self);
    }

    void uninitialize()
    {
        ServerApplication::uninitialize();
    }

    void defineOptions(OptionSet& options)
    {
        ServerApplication::defineOptions(options);

        options.addOption(
            Option("help", "h", "display help information on command line arguments")
            .required(false)
            .repeatable(false));
    }

    void handleOption(const std::string& name, const std::string& value)
    {
        ServerApplication::handleOption(name, value);

        if (name == "help")
            _helpRequested = true;
    }

    void displayHelp()
    {
        HelpFormatter helpFormatter(options());
        helpFormatter.setCommand(commandName());
        helpFormatter.setUsage("OPTIONS");
        helpFormatter.setHeader("A server application that serves the current date and time.");
        helpFormatter.format(std::cout);
    }

    int main(const std::vector<std::string>& args)
    {
        if (_helpRequested)
        {
            displayHelp();
        }
        else
        {
            // get parameters from configuration file
            unsigned short port = (unsigned short)config().getInt("TimeServer.port", 9911);
            std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));

            // set-up a server socket
            ServerSocket svs(port);
            // set-up a TCPServer instance
            TCPServer srv(new TimeServerConnectionFactory(format), svs);
            // start the TCPServer
            srv.start();
            // wait for CTRL-C or kill
            waitForTerminationRequest();
            // Stop the TCPServer
            srv.stop();
        }
        return Application::EXIT_OK;
    }

private:
    bool _helpRequested;
};


int main(int argc, char** argv)
{
    TimeServer app; // 9911
    return app.run(argc, argv);
}

start tcpserver.

tcpclient

//
// TimeClient.cpp
//

#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include <iostream>

using Poco::Net::SocketAddress;
using Poco::Net::StreamSocket;

int main(int argc, char** argv)
{
    SocketAddress sa("127.0.0.1",9911);
    StreamSocket ss(sa);
    int n;
    char buffer[256];
    
    //n = 11 , s[0,1,2,....10] = hello world s[11]='
//
// TimeClient.cpp
//
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include <iostream>
using Poco::Net::SocketAddress;
using Poco::Net::StreamSocket;
int main(int argc, char** argv)
{
SocketAddress sa("127.0.0.1",9911);
StreamSocket ss(sa);
int n;
char buffer[256];
//n = 11 , s[0,1,2,....10] = hello world s[11]='\0'
n = ss.receiveBytes(buffer, sizeof(buffer)-1);
buffer[n] = '\0';
std::cout << buffer << std::endl;
std::cout << n << std::endl;
}
' n = ss.receiveBytes(buffer, sizeof(buffer)-1); buffer[n] = '
//
// TimeClient.cpp
//
#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include <iostream>
using Poco::Net::SocketAddress;
using Poco::Net::StreamSocket;
int main(int argc, char** argv)
{
SocketAddress sa("127.0.0.1",9911);
StreamSocket ss(sa);
int n;
char buffer[256];
//n = 11 , s[0,1,2,....10] = hello world s[11]='\0'
n = ss.receiveBytes(buffer, sizeof(buffer)-1);
buffer[n] = '\0';
std::cout << buffer << std::endl;
std::cout << n << std::endl;
}
'; std::cout << buffer << std::endl; std::cout << n << std::endl; }

start tcpclient to receive data from tcpserver.

telnet as tcpclient

install telnet on windows by contron panel.

telnet localhost 9911

Reference

  • poco windows
  • poco guide
  • poco newwork pdf
  • poco net samples
  • poco tcpclient and tcpserver
  • poco tcpclient how to in detail

History

  • 20180125: created.

Copyright

  • Post author: kezunlin
  • Post link: https://kezunlin.me/post/9587bb47/
  • Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

Recommended Today

Manjaro uses SS method (requires nodejs environment)

Just installed manjaro, need to installshadowsocks-qt5+Proxy SwitchyOmega, but the latest Chrome has long blocked the installation of non Google store CRX channels. Here is my solution, which is troublesome but usable. If you are familiar with NPM commands in nodejs, you won’t find it troublesome, because nodejs is used for compilation. Preparation environment: A VPS […]