Несколько Http-серверов с Poco и Boost C++
Я пытаюсь создать несколько серверов Http с библиотеками Poco::Net и Boost, но внутри Poco-файла Application.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();
}
};
Это основной код сервера, и я, например, создаю серверы в главной функции. Вызов service.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
объект, прежде чем использовать его в любом потоке.