POCOで簡単Webサーバ

C++のライブラリ,POCOの紹介キャンペーンの続きです.

POCOで簡単SMTPプレーンテキストメール - なぜか数学者にはワイン好きが多い
POCOで簡単SMTPアクセス - なぜか数学者にはワイン好きが多い
POCOで簡単POPアクセス - なぜか数学者にはワイン好きが多い
POCOで簡単Webアクセス - なぜか数学者にはワイン好きが多い

ApacheみたいなWebサーバの簡単バージョンを書いてみます.静的なページだけが対象.

今回はデーモンにするので,ヘッダ部分だけでこれくらいになります.

*#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/ThreadPool.h"
#include "Poco/Thread.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/RunnableAdapter.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::ThreadPool;
using Poco::Thread;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::RunnableAdapter;
using namespace std;


手抜きして,ヘッダファイルのクラス宣言部分に定義も全部書いてしまいます.

class WWWRequestHandler: public HTTPRequestHandler
{
public:
  WWWRequestHandler()  { } // なんもしない
  void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response)
  {
    // 適当な表示内容を...
    response.setChunkedTransferEncoding(true);
    response.setContentType("text/html");
    std::ostream& ostr = response.send();
    ostr << "<html><head><title>WWW Server</title>";
    ostr << "<body><p style=\"text-align: center; font-size: 48px;\">";
    ostr << "WWW Server by POCO C++ Libraries"<<"<BR />";
    ostr << "YOUR REQUEST="<<request.getURI()<<"<BR />";
    ostr << "YOUR ADDRESS="<<request.clientAddress().toString()<<"<BR />";
    ostr << "</p></body></html>";
  }
};

class WWWRequestHandlerFactory: public HTTPRequestHandlerFactory
{
public:
  WWWRequestHandlerFactory()  {  }
  HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request)
  {
    return new WWWRequestHandler();
  }
};


class WWWServer: public Poco::Util::ServerApplication
{
public:
  WWWServer()  {  }
  ~WWWServer()  {  }
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);
  }
  void handleOption(const std::string& name, const std::string& value)
  {
    ServerApplication::handleOption(name, value);
  }
  int main(const std::vector<std::string>& args)
  {
    unsigned short port = (unsigned short) config().getInt("WWWServer.port", 8888);
    int maxQueued  = config().getInt("WWWServer.maxQueued", 100);
    int maxThreads = config().getInt("WWWServer.maxThreads", 16);
    ThreadPool::defaultPool().addCapacity(maxThreads);
    HTTPServerParams* pParams = new HTTPServerParams;
    pParams->setMaxQueued(maxQueued);
    pParams->setMaxThreads(maxThreads);
    ServerSocket svs(port);
    HTTPServer srv(new WWWRequestHandlerFactory(), svs, pParams);
    srv.start();
    waitForTerminationRequest(); // CTRL-Cが押されるか,killでシグナルを送られるまで待つ
    srv.stop();
    return Application::EXIT_OK;
  }
};

このプログラムをコンパイルします.

> c++ -o httpd httpd.cc -I/usr/local/include -L/usr/local/lib -lPocoNet -lPocoUtil

実行します.

 ./httpd  

ローカルでアクセスしてみます.

> w3m http://localhost:8888/

Ok.
ポートを8888にしているのは,ポート80にしてコンパイル&実行するとエラーが出たからです.

> ./httpd
I/O error: Permission denied

これはよく分かんなかったので,また調べます.
(全部rootで作業するとエラーは出ないのですが...)