Как я могу запустить несколько ServerApplications с POCO C++?
Я начал изучать библиотеку POCO C++ и застрял при попытке запустить 2 сервера в одном приложении (чтобы они могли использовать некоторые общие переменные времени выполнения). Это 2 разных сервера, один из которых - TCP TimeServer, а другой - простой UDP EchoServer. Код:
#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Net/DatagramSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>
using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServer;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
class TimeServerConnection : public TCPServerConnection
{
public:
TimeServerConnection(const StreamSocket& s, const std::string& format) :
TCPServerConnection(s),
_format(format)
{
}
void run()
{
Application& app = Application::instance();
bool isOpen = true;
Poco::Timespan timeOut(10, 0);
unsigned char incommingBuffer[1000];
app.logger().information("SYSLOG from " + this->socket().peerAddress().toString());
while (isOpen) {
if (socket().poll(timeOut, Poco::Net::Socket::SELECT_READ) == false) {
std::cout << "TIMEOUT!" << std::endl << std::flush;
} else {
int nBytes = -1;
try {
nBytes = socket().receiveBytes(incommingBuffer, sizeof(incommingBuffer));
std::cout << incommingBuffer << std::endl;
} catch (Poco::Exception& exc) {
std::cerr << "Network error: " << exc.displayText() << std::endl;
isOpen = false;
}
if (nBytes == 0) {
std::cout << "Client closes connection!" << std::endl << std::flush;
isOpen = false;
} else {
std::cout << "Receiving nBytes: " << nBytes << std::endl << std::flush;
}
}
}
try
{
Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));
dt.append("\r\n");
socket().sendBytes(dt.data(), (int)dt.length());
}
catch (Poco::Exception& exc)
{ app.logger().log(exc); }
}
private:
std::string _format;
};
class TimeServerConnectionFactory : public TCPServerConnectionFactory
{
public:
TimeServerConnectionFactory(const std::string& format) :
_format(format)
{
}
TCPServerConnection* createConnection(const StreamSocket& socket)
{ return new TimeServerConnection(socket, _format); }
private:
std::string _format;
};
class UDPServer : public Poco::Util::ServerApplication
{
public:
UDPServer(){}
~UDPServer(){}
protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}
void uninitialize() { ServerApplication::uninitialize(); }
int main(const std::vector<std::string>& args)
{
unsigned short port = (unsigned short)config().getInt("udpport", 9002);
std::cout << "[UDP] Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
Poco::Net::SocketAddress socketaddress(Poco::Net::IPAddress(), 9001);
Poco::Net::DatagramSocket datagramsocket(socketaddress);
char buffer[1024]; // 1K byte
while (1) {
Poco::Net::SocketAddress sender;
int n = datagramsocket.receiveFrom(buffer, sizeof(buffer) - 1, sender);
buffer[n] = '\0';
std::cout << sender.toString() << ":" << buffer << std::endl;
}
return 0;
}
};
class TimeServer : public Poco::Util::ServerApplication
{
public:
TimeServer() : _helpRequested(false)
{
}
~TimeServer()
{
}
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);
options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}
void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);
if (name == "help")
_helpRequested = true;
}
void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A server application that serves the current date and time.");
helpFormatter.format(std::cout);
}
int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
unsigned short port = (unsigned short)config().getInt("tcpport", 9911);
std::cout << "Using port " << port << std::endl;
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));
ServerSocket svs(port);
TCPServer srv(new TimeServerConnectionFactory(format), svs);
srv.start();
std::cout << "Server started!\n";
waitForTerminationRequest();
srv.stop();
std::cout << "Server stopped!\n";
}
return Application::EXIT_OK;
}
private:
bool _helpRequested;
};
int main(int argc, char** argv)
{
TimeServer app;
UDPServer app2;
app.run(argc, argv);
app2.run(argc, argv);
}
В конце кода у меня есть int main()
метод, в котором я пытаюсь запустить 2 сервера. Однако я получаю нарушение утверждения здесь. Есть похожий вопрос по Stackru, однако boost
используется там, в то время как я использую простой C++, так что решение не относится ко мне.
Как я могу запустить одновременно эти 2 сервера?
2 ответа
ServerApplication
не был предназначен для нескольких экземпляров. Что вы должны сделать, это запустить один ServerApplication
и запустите TCPServer и UDPServer в этом приложении.
На самом деле, если вы хотите сделать так (как вы задаете вопрос), разделите класс tcp (a) и класс udp (b).
Вызовите оба из другого класса (c) и определите, какой (c) -> (a) (c) -> (b) вам нужно вызвать первым и когда. Так что вам нужно принять условие и решение.
Примечание: дайте им время перед бегом, чтобы сделать дыхание поко.