1 | // |
2 | // TimeServer.cpp |
3 | // |
4 | // This sample demonstrates the TCPServer and ServerSocket classes. |
5 | // |
6 | // Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH. |
7 | // and Contributors. |
8 | // |
9 | // SPDX-License-Identifier: BSL-1.0 |
10 | // |
11 | |
12 | |
13 | #include "Poco/Net/TCPServer.h" |
14 | #include "Poco/Net/TCPServerConnection.h" |
15 | #include "Poco/Net/TCPServerConnectionFactory.h" |
16 | #include "Poco/Net/TCPServerParams.h" |
17 | #include "Poco/Net/StreamSocket.h" |
18 | #include "Poco/Net/ServerSocket.h" |
19 | #include "Poco/Timestamp.h" |
20 | #include "Poco/DateTimeFormatter.h" |
21 | #include "Poco/DateTimeFormat.h" |
22 | #include "Poco/Exception.h" |
23 | #include "Poco/Util/ServerApplication.h" |
24 | #include "Poco/Util/Option.h" |
25 | #include "Poco/Util/OptionSet.h" |
26 | #include "Poco/Util/HelpFormatter.h" |
27 | #include <iostream> |
28 | |
29 | |
30 | using Poco::Net::ServerSocket; |
31 | using Poco::Net::StreamSocket; |
32 | using Poco::Net::TCPServerConnection; |
33 | using Poco::Net::TCPServerConnectionFactory; |
34 | using Poco::Net::TCPServer; |
35 | using Poco::Timestamp; |
36 | using Poco::DateTimeFormatter; |
37 | using Poco::DateTimeFormat; |
38 | using Poco::Util::ServerApplication; |
39 | using Poco::Util::Application; |
40 | using Poco::Util::Option; |
41 | using Poco::Util::OptionSet; |
42 | using Poco::Util::HelpFormatter; |
43 | |
44 | |
45 | class TimeServerConnection: public TCPServerConnection |
46 | /// This class handles all client connections. |
47 | /// |
48 | /// A string with the current date and time is sent back to the client. |
49 | { |
50 | public: |
51 | TimeServerConnection(const StreamSocket& s, const std::string& format): |
52 | TCPServerConnection(s), |
53 | _format(format) |
54 | { |
55 | } |
56 | |
57 | void run() |
58 | { |
59 | Application& app = Application::instance(); |
60 | app.logger().information("Request from " + this->socket().peerAddress().toString()); |
61 | try |
62 | { |
63 | Timestamp now; |
64 | std::string dt(DateTimeFormatter::format(now, _format)); |
65 | dt.append("\r\n" ); |
66 | socket().sendBytes(dt.data(), (int) dt.length()); |
67 | } |
68 | catch (Poco::Exception& exc) |
69 | { |
70 | app.logger().log(exc); |
71 | } |
72 | } |
73 | |
74 | private: |
75 | std::string _format; |
76 | }; |
77 | |
78 | |
79 | class TimeServerConnectionFactory: public TCPServerConnectionFactory |
80 | /// A factory for TimeServerConnection. |
81 | { |
82 | public: |
83 | TimeServerConnectionFactory(const std::string& format): |
84 | _format(format) |
85 | { |
86 | } |
87 | |
88 | TCPServerConnection* createConnection(const StreamSocket& socket) |
89 | { |
90 | return new TimeServerConnection(socket, _format); |
91 | } |
92 | |
93 | private: |
94 | std::string _format; |
95 | }; |
96 | |
97 | |
98 | class TimeServer: public Poco::Util::ServerApplication |
99 | /// The main application class. |
100 | /// |
101 | /// This class handles command-line arguments and |
102 | /// configuration files. |
103 | /// Start the TimeServer executable with the help |
104 | /// option (/help on Windows, --help on Unix) for |
105 | /// the available command line options. |
106 | /// |
107 | /// To use the sample configuration file (TimeServer.properties), |
108 | /// copy the file to the directory where the TimeServer executable |
109 | /// resides. If you start the debug version of the TimeServer |
110 | /// (TimeServerd[.exe]), you must also create a copy of the configuration |
111 | /// file named TimeServerd.properties. In the configuration file, you |
112 | /// can specify the port on which the server is listening (default |
113 | /// 9911) and the format of the date/time string sent back to the client. |
114 | /// |
115 | /// To test the TimeServer you can use any telnet client (telnet localhost 9911). |
116 | { |
117 | public: |
118 | TimeServer(): _helpRequested(false) |
119 | { |
120 | } |
121 | |
122 | ~TimeServer() |
123 | { |
124 | } |
125 | |
126 | protected: |
127 | void initialize(Application& self) |
128 | { |
129 | loadConfiguration(); // load default configuration files, if present |
130 | ServerApplication::initialize(self); |
131 | } |
132 | |
133 | void uninitialize() |
134 | { |
135 | ServerApplication::uninitialize(); |
136 | } |
137 | |
138 | void defineOptions(OptionSet& options) |
139 | { |
140 | ServerApplication::defineOptions(options); |
141 | |
142 | options.addOption( |
143 | Option("help" , "h" , "display help information on command line arguments" ) |
144 | .required(false) |
145 | .repeatable(false)); |
146 | } |
147 | |
148 | void handleOption(const std::string& name, const std::string& value) |
149 | { |
150 | ServerApplication::handleOption(name, value); |
151 | |
152 | if (name == "help" ) |
153 | _helpRequested = true; |
154 | } |
155 | |
156 | void displayHelp() |
157 | { |
158 | HelpFormatter helpFormatter(options()); |
159 | helpFormatter.setCommand(commandName()); |
160 | helpFormatter.setUsage("OPTIONS" ); |
161 | helpFormatter.setHeader("A server application that serves the current date and time." ); |
162 | helpFormatter.format(std::cout); |
163 | } |
164 | |
165 | int main(const std::vector<std::string>& args) |
166 | { |
167 | if (_helpRequested) |
168 | { |
169 | displayHelp(); |
170 | } |
171 | else |
172 | { |
173 | // get parameters from configuration file |
174 | unsigned short port = (unsigned short) config().getInt("TimeServer.port" , 9911); |
175 | std::string format(config().getString("TimeServer.format" , DateTimeFormat::ISO8601_FORMAT)); |
176 | |
177 | // set-up a server socket |
178 | ServerSocket svs(port); |
179 | // set-up a TCPServer instance |
180 | TCPServer srv(new TimeServerConnectionFactory(format), svs); |
181 | // start the TCPServer |
182 | srv.start(); |
183 | // wait for CTRL-C or kill |
184 | waitForTerminationRequest(); |
185 | // Stop the TCPServer |
186 | srv.stop(); |
187 | } |
188 | return Application::EXIT_OK; |
189 | } |
190 | |
191 | private: |
192 | bool _helpRequested; |
193 | }; |
194 | |
195 | |
196 | int main(int argc, char** argv) |
197 | { |
198 | TimeServer app; |
199 | return app.run(argc, argv); |
200 | } |
201 | |