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 int a_avgResponseTime;
87 int a_rxMessageCounter;
88 MyHandler a_httpHandler;
90 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
92 void eventBreakConnection (const ClientSocket&) throw ();
94 void eventBreakConnection (Server* server) throw () {
95 comm::Communicator::eventBreakConnection (server);
97 void eventBreakConnection (const Service* service) throw () {
98 comm::Communicator::eventBreakConnection (service);
102 class HeavyClient : public anna::comm::Application {
106 Server* getServer () const throw () { return a_server; }
107 const Sender* getSender () const throw () { return &a_sender; }
110 MyCommunicator a_communicator;
111 anna::timex::Engine a_timeController;
115 void initialize () throw (RuntimeException);
116 void run () throw (RuntimeException);
121 int main (int argc, const char** argv)
123 CommandLine& commandLine (CommandLine::instantiate ());
129 commandLine.initialize (argv, argc);
130 commandLine.verify ();
132 Logger::setLevel (Logger::Information);
133 string traceFile ("client.");
134 traceFile += anna::functions::asString ((int) getpid ());
135 traceFile += ".trace";
136 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
140 catch (Exception& ex) {
141 cout << ex.asString () << endl;
147 HeavyClient::HeavyClient () :
148 Application ("http_client", "Cliente HTTP", "1.0"),
150 a_timeController ((Millisecond)1000, (Millisecond)250)
152 CommandLine& commandLine (CommandLine::instantiate ());
154 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
155 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
156 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
157 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
160 void HeavyClient::initialize ()
161 throw (RuntimeException)
163 CommandLine& cl (CommandLine::instantiate ());
165 Network& network = Network::instantiate ();
167 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
168 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
170 if (cl.exists ("trace"))
171 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
174 void HeavyClient::run ()
175 throw (RuntimeException)
177 a_timeController.activate (a_sender);
179 a_communicator.accept ();
182 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
183 throw (RuntimeException)
185 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
187 if (clientSocket.support (http::Transport::className ()) == false)
190 a_httpHandler.apply (clientSocket, message);
193 void MyCommunicator::count (const int delay)
194 throw (RuntimeException)
196 Guard guard (this, "MyCommunicator::eventReceiveMessage");
198 a_rxMessageCounter ++;
199 a_avgResponseTime += delay;
202 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
205 if (a_rxMessageCounter == 0)
209 HeavyClient& app = static_cast <HeavyClient&> (anna::app::functions::getApp ());
210 string msg ("Tiempo medio respuesta: ");
211 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
213 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
214 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
215 Logger::notice (msg, ANNA_FILE_LOCATION);
217 cout << msg << endl << endl;
220 comm::Communicator::eventBreakConnection (clientSocket);
224 throw (RuntimeException)
226 Server* server = static_cast <HeavyClient&> (anna::app::functions::getApp ()).getServer ();
227 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
229 if (a_errorCounter > 100) {
230 communicator->requestStop ();
231 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
235 for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
236 a_testRequest.op = '+';
237 a_testRequest.x = rand () % 1000;
238 a_testRequest.y = rand () % 1000;
239 a_testRequest.initTime = anna::functions::millisecond ();
242 a_httpRequest.setBody (a_testRequest.code ());
243 server->send (a_httpRequest);
244 a_txMessageCounter ++;
246 catch (RuntimeException& ex) {
256 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
257 throw (RuntimeException)
259 if (response.getStatusCode () == 200) {
260 a_testResponse.decode (response.getBody ());
262 test::Response& response (a_testResponse);
264 const anna::Millisecond now = anna::functions::millisecond ();
265 const int delay = now - (Millisecond) response.initTime;
267 if (delay > 0 && isOk (response) == true) {
268 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (delay);
271 string msg = anna::functions::asString (
272 "%d %c %d = %d", response.x, response.op, response.y, response.result
274 msg += anna::functions::asText (" | Delay: ", delay);
275 Logger::information (msg, ANNA_FILE_LOCATION);
280 string msg = anna::functions::asString (
281 "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
283 msg += anna::functions::asText (" | Message: ", response.getBody ());
284 msg += anna::functions::asText (" | Delay: ", delay);
285 Logger::warning (msg, ANNA_FILE_LOCATION);
291 bool MyHandler::isOk (const test::Response& response)
294 if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/')
299 switch (response.op) {
301 result = response.x + response.y;
304 result = response.x - response.y;
307 result = response.x * response.y;
310 result = (response.y != 0) ? (response.x / response.y): 0;
314 return result == response.result;