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で作業するとエラーは出ないのですが...)