Несколько Http серверов с Poco и Boost C++
Я пытаюсь создать несколько Http-серверов с библиотеками Poco::Net и Boost, но в приложении Poco file возникает следующая ошибка.cpp :
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Assertion violation: _pInstance == 0 [in file "src/Application.cpp", line 115]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Я использую следующий код:
#include <Poco/Net/HTMLForm.h>
#include <Poco/Net/HTTPServerRequest.h>
#include <Poco/Net/HTTPServerResponse.h>
#include <boost/asio/io_service.hpp>
boost::asio::io_service service(100);
class RequestHandler : public Poco::Net::HTTPRequestHandler {
public:
RequestHandler(){}
void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response){}
};
class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory {
public:
RequestHandlerFactory(){}
Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request)
{
return new RequestHandler();
}
};
class HttpServer :
public Poco::Util::ServerApplication,
public boost::enable_shared_from_this<HttpServer>{
Poco::Net::ServerSocket svs;
Poco::Net::HTTPServer srv;
public:
HttpServer(std::string address_, Poco::UInt16 port_):
svs(Poco::Net::SocketAddress(address_.empty() ? "127.0.0.1" : address_, port_)),
srv(new RequestHandlerFactory(), svs, new Poco::Net::HTTPServerParams)
{
svs.setReuseAddress(true);
svs.setReusePort(true);
}
virtual ~HttpServer(){}
void start()
{
service.post(
boost::bind(&HttpServer::exec, shared_from_this()));
}
void stop()
{
srv.stop();
}
private:
void exec()
{
srv.start();
waitForTerminationRequest();
srv.stop();
}
};
Это основной код сервера, и я создаю серверы в главной функции, например.
Служба .post вызов, предназначен для асинхронного вызова метода exec и построения service(100) относится к пулу потоков размером 100.
Сервер создается следующим образом:
boost::shared_ptr<HttpServer> server(
new HttpServer("", 8080));
boost::shared_ptr<HttpServer> server2(
new HttpServer("", 8181));
server->start();
server2->start(); // Error occurs here
Ошибка отображается при запуске второго сервера.
1 ответ:
HttpServerApplicationне предназначен для использования таким образом. Он спроектирован как синглтон.Http://pocoproject.org/docs/Poco.Util.ServerApplication.html
Вы можете исправить эту часть, не производя от
ServerApplicationв вашем классеHttpServer. В конце концов, вам нужно несколько серверов, а не приложений.В моем простейшем тесте работает следующее:
#include <Poco/Net/HTMLForm.h> #include <Poco/Net/HTTPRequestHandler.h> #include <Poco/Net/HTTPRequestHandlerFactory.h> #include <Poco/Net/ServerSocket.h> #include <Poco/Net/HTTPServer.h> #include <Poco/Util/ServerApplication.h> #include <Poco/Net/HTTPServerRequest.h> #include <Poco/Net/HTTPServerResponse.h> #include <boost/enable_shared_from_this.hpp> #include <boost/asio/io_service.hpp> #include <boost/make_shared.hpp> #include <boost/bind.hpp> boost::asio::io_service service(100); class RequestHandler : public Poco::Net::HTTPRequestHandler { public: RequestHandler(){} void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response){} }; class RequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { public: RequestHandlerFactory(){} Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) { return new RequestHandler(); } }; class HttpServer : public boost::enable_shared_from_this<HttpServer>{ Poco::Net::ServerSocket svs; Poco::Net::HTTPServer srv; public: HttpServer(std::string address_, Poco::UInt16 port_): svs(Poco::Net::SocketAddress(address_.empty() ? "127.0.0.1" : address_, port_)), srv(new RequestHandlerFactory(), svs, new Poco::Net::HTTPServerParams) { svs.setReuseAddress(true); svs.setReusePort(true); } virtual ~HttpServer(){} void start() { service.post( boost::bind(&HttpServer::exec, shared_from_this())); } void stop() { srv.stop(); } private: void exec() { srv.start(); } };В
mainя создаю подклассServerApplicationс единственной целью клонирования защищенного методаwaitForTerminationRequest()Перед выходом из главного. Если вам нужен синтаксический анализ аргументов, конечно, передайтеargc, argvвapp.run. Но в данный момент я не вижу в этом необходимости.int main() { struct App : Poco::Util::ServerApplication { ~App() { waitForTerminationRequest(); } } app; for (int i=0; i<2; ++i) { boost::make_shared<HttpServer>("", 8080+i)->start(); } }
СТАРЫЙ ТЕКСТ ОТВЕТА
Как вы создаете экземпляры объектов
HttpServer?
Вы должны, очевидно, использовать
boost::make_shared<HttpServer>(host, port)(илиshared_ptr<HttpServer>(new HttpServer(host, port))), Чтобыenable_shared_from_thisбыло разрешено. Не забудьте сохранить общий ptr по крайней мере до тех пор, пока служба не будет запущена (отправив вызовexec()вio_service).В частности, это незаконное:
for (int i=0; i<10; ++i) { HttpServer s("", 8080+i); s.start(); }Вместо этого используйте, например,
for (int i=0; i<10; ++i) { boost::make_shared<HttpServer>("", 8080+i)->start(); }Кроме того, если вы собираетесь запустить его в пуле из 100 потоков, Вы нужда либо использовать
strand(для логического потока выполнения) или заблокируйте ОбъектHttpServerперед его использованием в любом потоке.
Comments