1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
38 Realiza peticiones automaticas sobre el servidor HTTP de operaciones aritmeticas.
40 La cadencia de envio de mensajes se establece mediante un temporizador.
41 Los operadores se calculan de forma aleatoria.
43 El servidor de este cliente: http_server.p o http_rserver.p
51 #include <anna/core/core.hpp>
52 #include <anna/app/functions.hpp>
53 #include <anna/comm/comm.hpp>
55 #include <anna/timex/Engine.hpp>
56 #include <anna/timex/Clock.hpp>
58 #include <anna/http/Request.hpp>
59 #include <anna/http/Response.hpp>
60 #include <anna/http/Transport.hpp>
61 #include <anna/http/Handler.hpp>
63 #include <anna/test/Response.hpp>
64 #include <anna/test/Request.hpp>
66 class Sender : public anna::timex::Clock {
68 Sender () : Clock ("Sender", (Millisecond)1000),
69 a_messageBySecond (0),
72 a_txMessageCounter (0)
74 a_httpRequest.setMethod (http::Method::Type::Post);
75 a_httpRequest.setURI ("HTTPKClient");
78 void setMessageBySecond (const int messageBySecond) throw () { a_messageBySecond = messageBySecond; }
80 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
83 int a_messageBySecond;
86 int a_txMessageCounter;
87 http::Request a_httpRequest;
88 test::Request a_testRequest;
90 bool tick () throw (RuntimeException);
93 class MyHandler : public http::Handler {
95 MyHandler () : http::Handler ("http_client::MyHandler") {;}
98 http::Response a_httpResponse;
99 test::Response a_testResponse;
101 void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
102 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
104 static bool isOk (const test::Response& response) throw ();
107 class MyCommunicator : public Communicator {
109 MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0) {;}
111 void count (const int delay) throw (RuntimeException);
114 int a_avgResponseTime;
115 int a_rxMessageCounter;
116 MyHandler a_httpHandler;
118 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
120 void eventBreakConnection (const ClientSocket&) throw ();
122 void eventBreakConnection (Server* server) throw () {
123 comm::Communicator::eventBreakConnection (server);
125 void eventBreakConnection (const Service* service) throw () {
126 comm::Communicator::eventBreakConnection (service);
130 class HeavyClient : public anna::comm::Application {
134 Server* getServer () const throw () { return a_server; }
135 const Sender* getSender () const throw () { return &a_sender; }
138 MyCommunicator a_communicator;
139 anna::timex::Engine a_timeController;
143 void initialize () throw (RuntimeException);
144 void run () throw (RuntimeException);
149 int main (int argc, const char** argv)
151 CommandLine& commandLine (CommandLine::instantiate ());
157 commandLine.initialize (argv, argc);
158 commandLine.verify ();
160 Logger::setLevel (Logger::Information);
161 string traceFile ("client.");
162 traceFile += anna::functions::asString ((int) getpid ());
163 traceFile += ".trace";
164 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
168 catch (Exception& ex) {
169 cout << ex.asString () << endl;
175 HeavyClient::HeavyClient () :
176 Application ("http_client", "Cliente HTTP", "1.0"),
178 a_timeController ((Millisecond)1000, (Millisecond)250)
180 CommandLine& commandLine (CommandLine::instantiate ());
182 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
183 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
184 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
185 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
188 void HeavyClient::initialize ()
189 throw (RuntimeException)
191 CommandLine& cl (CommandLine::instantiate ());
193 Network& network = Network::instantiate ();
195 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
196 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
198 if (cl.exists ("trace"))
199 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
202 void HeavyClient::run ()
203 throw (RuntimeException)
205 a_timeController.activate (a_sender);
207 a_communicator.accept ();
210 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
211 throw (RuntimeException)
213 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
215 if (clientSocket.support (http::Transport::className ()) == false)
218 a_httpHandler.apply (clientSocket, message);
221 void MyCommunicator::count (const int delay)
222 throw (RuntimeException)
224 Guard guard (this, "MyCommunicator::eventReceiveMessage");
226 a_rxMessageCounter ++;
227 a_avgResponseTime += delay;
230 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
233 if (a_rxMessageCounter == 0)
237 HeavyClient& app = static_cast <HeavyClient&> (anna::app::functions::getApp ());
238 string msg ("Tiempo medio respuesta: ");
239 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
241 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
242 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
243 Logger::notice (msg, ANNA_FILE_LOCATION);
245 cout << msg << endl << endl;
248 comm::Communicator::eventBreakConnection (clientSocket);
252 throw (RuntimeException)
254 Server* server = static_cast <HeavyClient&> (anna::app::functions::getApp ()).getServer ();
255 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
257 if (a_errorCounter > 100) {
258 communicator->requestStop ();
259 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
263 for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
264 a_testRequest.op = '+';
265 a_testRequest.x = rand () % 1000;
266 a_testRequest.y = rand () % 1000;
267 a_testRequest.initTime = anna::functions::millisecond ();
270 a_httpRequest.setBody (a_testRequest.code ());
271 server->send (a_httpRequest);
272 a_txMessageCounter ++;
274 catch (RuntimeException& ex) {
284 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
285 throw (RuntimeException)
287 if (response.getStatusCode () == 200) {
288 a_testResponse.decode (response.getBody ());
290 test::Response& response (a_testResponse);
292 const anna::Millisecond now = anna::functions::millisecond ();
293 const int delay = now - (Millisecond) response.initTime;
295 if (delay > 0 && isOk (response) == true) {
296 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (delay);
299 string msg = anna::functions::asString (
300 "%d %c %d = %d", response.x, response.op, response.y, response.result
302 msg += anna::functions::asText (" | Delay: ", delay);
303 Logger::information (msg, ANNA_FILE_LOCATION);
308 string msg = anna::functions::asString (
309 "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
311 msg += anna::functions::asText (" | Message: ", response.getBody ());
312 msg += anna::functions::asText (" | Delay: ", delay);
313 Logger::warning (msg, ANNA_FILE_LOCATION);
319 bool MyHandler::isOk (const test::Response& response)
322 if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/')
327 switch (response.op) {
329 result = response.x + response.y;
332 result = response.x - response.y;
335 result = response.x * response.y;
338 result = (response.y != 0) ? (response.x / response.y): 0;
342 return result == response.result;