1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
10 Realiza peticiones automaticas sobre el servidor HTTP de operaciones aritmeticas.
12 La cadencia de envio de mensajes se establece mediante un temporizador.
13 Los operadores se calculan de forma aleatoria.
15 El servidor de este cliente: http_server.p o http_rserver.p
23 #include <anna/core/core.hpp>
24 #include <anna/app/functions.hpp>
25 #include <anna/comm/comm.hpp>
27 #include <anna/timex/Engine.hpp>
28 #include <anna/timex/Clock.hpp>
30 #include <anna/http/Request.hpp>
31 #include <anna/http/Response.hpp>
32 #include <anna/http/Transport.hpp>
33 #include <anna/http/Handler.hpp>
35 #include <anna/test/Response.hpp>
36 #include <anna/test/Request.hpp>
38 class Sender : public anna::timex::Clock {
40 Sender () : Clock ("Sender", (Millisecond)1000),
41 a_messageBySecond (0),
44 a_txMessageCounter (0)
46 a_httpRequest.setMethod (http::Method::Type::Post);
47 a_httpRequest.setURI ("HTTPKClient");
50 void setMessageBySecond (const int messageBySecond) throw () { a_messageBySecond = messageBySecond; }
52 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
55 int a_messageBySecond;
58 int a_txMessageCounter;
59 http::Request a_httpRequest;
60 test::Request a_testRequest;
62 bool tick () throw (RuntimeException);
65 class MyHandler : public http::Handler {
67 MyHandler () : http::Handler ("http_client::MyHandler") {;}
70 http::Response a_httpResponse;
71 test::Response a_testResponse;
73 void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
74 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
76 static bool isOk (const test::Response& response) throw ();
79 class MyCommunicator : public Communicator {
81 MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0) {;}
83 void count (const int delay) throw (RuntimeException);
86 using Communicator::eventBreakConnection;
88 int a_avgResponseTime;
89 int a_rxMessageCounter;
90 MyHandler a_httpHandler;
92 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
94 void eventBreakConnection (const ClientSocket&) throw ();
96 void eventBreakConnection (Server* server) throw () {
97 comm::Communicator::eventBreakConnection (server);
99 void eventBreakConnection (const Service* service) throw () {
100 comm::Communicator::eventBreakConnection (service);
104 class HeavyClient : public anna::comm::Application {
108 Server* getServer () const throw () { return a_server; }
109 const Sender* getSender () const throw () { return &a_sender; }
112 MyCommunicator a_communicator;
113 anna::timex::Engine a_timeController;
117 void initialize () throw (RuntimeException);
118 void run () throw (RuntimeException);
123 int main (int argc, const char** argv)
125 CommandLine& commandLine (CommandLine::instantiate ());
131 commandLine.initialize (argv, argc);
132 commandLine.verify ();
134 Logger::setLevel (Logger::Information);
135 string traceFile ("client.");
136 traceFile += anna::functions::asString ((int) getpid ());
137 traceFile += ".trace";
138 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
142 catch (Exception& ex) {
143 cout << ex.asString () << endl;
149 HeavyClient::HeavyClient () :
150 Application ("http_client", "Cliente HTTP", "1.0"),
152 a_timeController ((Millisecond)1000, (Millisecond)250)
154 CommandLine& commandLine (CommandLine::instantiate ());
156 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
157 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
158 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
159 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
162 void HeavyClient::initialize ()
163 throw (RuntimeException)
165 CommandLine& cl (CommandLine::instantiate ());
167 Network& network = Network::instantiate ();
169 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
170 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
172 if (cl.exists ("trace"))
173 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
176 void HeavyClient::run ()
177 throw (RuntimeException)
179 a_timeController.activate (a_sender);
181 a_communicator.accept ();
184 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
185 throw (RuntimeException)
187 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
189 if (clientSocket.support (http::Transport::className ()) == false)
192 a_httpHandler.apply (clientSocket, message);
195 void MyCommunicator::count (const int delay)
196 throw (RuntimeException)
198 Guard guard (this, "MyCommunicator::eventReceiveMessage");
200 a_rxMessageCounter ++;
201 a_avgResponseTime += delay;
204 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
207 if (a_rxMessageCounter == 0)
211 HeavyClient& app = static_cast <HeavyClient&> (anna::app::functions::getApp ());
212 string msg ("Tiempo medio respuesta: ");
213 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
215 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
216 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
217 Logger::notice (msg, ANNA_FILE_LOCATION);
219 cout << msg << endl << endl;
222 comm::Communicator::eventBreakConnection (clientSocket);
226 throw (RuntimeException)
228 Server* server = static_cast <HeavyClient&> (anna::app::functions::getApp ()).getServer ();
229 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
231 if (a_errorCounter > 100) {
232 communicator->requestStop ();
233 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
237 for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
238 a_testRequest.op = '+';
239 a_testRequest.x = rand () % 1000;
240 a_testRequest.y = rand () % 1000;
241 a_testRequest.initTime = anna::functions::millisecond ();
244 a_httpRequest.setBody (a_testRequest.code ());
245 server->send (a_httpRequest);
246 a_txMessageCounter ++;
248 catch (RuntimeException& ex) {
258 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
259 throw (RuntimeException)
261 if (response.getStatusCode () == 200) {
262 a_testResponse.decode (response.getBody ());
264 test::Response& response (a_testResponse);
266 const anna::Millisecond now = anna::functions::millisecond ();
267 const int delay = now - (Millisecond) response.initTime;
269 if (delay > 0 && isOk (response) == true) {
270 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (delay);
273 string msg = anna::functions::asString (
274 "%d %c %d = %d", response.x, response.op, response.y, response.result
276 msg += anna::functions::asText (" | Delay: ", delay);
277 Logger::information (msg, ANNA_FILE_LOCATION);
282 string msg = anna::functions::asString (
283 "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
285 msg += anna::functions::asText (" | Message: ", response.getBody ());
286 msg += anna::functions::asText (" | Delay: ", delay);
287 Logger::warning (msg, ANNA_FILE_LOCATION);
293 bool MyHandler::isOk (const test::Response& response)
296 if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/')
301 switch (response.op) {
303 result = response.x + response.y;
306 result = response.x - response.y;
309 result = response.x * response.y;
312 result = (response.y != 0) ? (response.x / response.y): 0;
316 return result == response.result;