使用 Poco 和 Boost C++ 的多个 Http 服务器
Multiple Http Servers with Poco and Boost C++
我正在尝试使用 Poco::Net 和 Boost 库创建多个 Http 服务器,但在 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)[= 的构造27=] 指的是大小为 100 的线程池。
服务器创建如下:
boost::shared_ptr<HttpServer> server(
new HttpServer("", 8080));
boost::shared_ptr<HttpServer> server2(
new HttpServer("", 8181));
server->start();
server2->start(); // Error occurs here
启动第二个服务器时显示错误。
HttpServerApplication
并非设计为以这种方式使用。它被设计成一个单例。
http://pocoproject.org/docs/Poco.Util.ServerApplication.html
您可以通过不从 HttpServer
class 中的 ServerApplication
派生来修复该部分。毕竟,您想要的是多台服务器,而不是应用程序。
在我最简单的测试中,以下工作:
#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
的子 class,唯一的原因是在退出 main 之前调用受保护的方法 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
对象你可以在任何线程上使用它。
- Why do I need strand per connection when using boost::asio?
我正在尝试使用 Poco::Net 和 Boost 库创建多个 Http 服务器,但在 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)[= 的构造27=] 指的是大小为 100 的线程池。
服务器创建如下:
boost::shared_ptr<HttpServer> server(
new HttpServer("", 8080));
boost::shared_ptr<HttpServer> server2(
new HttpServer("", 8181));
server->start();
server2->start(); // Error occurs here
启动第二个服务器时显示错误。
HttpServerApplication
并非设计为以这种方式使用。它被设计成一个单例。
http://pocoproject.org/docs/Poco.Util.ServerApplication.html
您可以通过不从 HttpServer
class 中的 ServerApplication
派生来修复该部分。毕竟,您想要的是多台服务器,而不是应用程序。
在我最简单的测试中,以下工作:
#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
的子 class,唯一的原因是在退出 main 之前调用受保护的方法 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
对象你可以在任何线程上使用它。- Why do I need strand per connection when using boost::asio?