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 de operaciones aritmeticas.
12 Mediante un servicio de reparto por RoundRobin.
14 El servidor de este cliente: server.p rserver.p
22 #include <anna/core/core.hpp>
23 #include <anna/app/functions.hpp>
24 #include <anna/comm/comm.hpp>
26 #include <anna/timex/Engine.hpp>
27 #include <anna/timex/Clock.hpp>
29 #include <anna/test/Response.hpp>
30 #include <anna/test/Request.hpp>
32 class Sender : public anna::timex::Clock {
34 Sender () : Clock ("Sender", (Millisecond)1000),
35 a_messageBySecond (0),
37 a_requests ("Request"),
39 a_txMessageCounter (0)
42 void setMessageBySecond (const int messageBySecond) { a_messageBySecond = messageBySecond; }
44 int getTxMessageCounter () const { return a_txMessageCounter; }
47 int a_messageBySecond;
50 int a_txMessageCounter;
51 ThreadData <test::Request> a_requests;
53 bool tick () noexcept(false);
56 class MyCommunicator : public Communicator {
58 MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0), a_responses ("Response") {;}
61 using Communicator::eventBreakConnection;
63 ThreadData <test::Response> a_responses;
64 int a_avgResponseTime;
65 int a_rxMessageCounter;
67 void eventReceiveMessage (ClientSocket &, const Message&) noexcept(false);
69 void eventBreakConnection (const ClientSocket&) ;
71 void eventBreakConnection (Server* server) {
72 comm::Communicator::eventBreakConnection (server);
75 void eventBreakConnection (const Service* service) ;
77 static bool isOk (const test::Response& response) ;
80 class RRClient : public anna::comm::Application {
84 Service* getService () const { return a_service; }
85 const Sender* getSender () const { return &a_sender; }
88 MyCommunicator a_communicator;
89 anna::timex::Engine a_timeController;
93 void initialize () noexcept(false);
94 void run () noexcept(false);
99 int main (int argc, const char** argv)
101 CommandLine& commandLine (CommandLine::instantiate ());
107 commandLine.initialize (argv, argc);
108 commandLine.verify ();
110 Logger::setLevel (Logger::Information);
111 string traceFile ("client.");
112 traceFile += anna::functions::asString ((int) getpid ());
113 traceFile += ".trace";
114 Logger::initialize ("arithmeticClient", new TraceWriter (traceFile.c_str (),4096000));
118 catch (Exception& ex) {
119 cout << ex.asString () << endl;
125 RRClient::RRClient () :
126 Application ("arithmeticClient", "Cliente de operaciones aritmeticas", "1.0"),
128 a_timeController ((Millisecond)1000, (Millisecond)250)
130 CommandLine& commandLine (CommandLine::instantiate ());
132 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puertos de los servidores (separados por comas)");
133 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
134 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
135 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
138 void RRClient::initialize ()
141 CommandLine& cl (CommandLine::instantiate ());
143 if (cl.exists ("trace"))
144 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
146 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
148 Network& network = Network::instantiate ();
149 Tokenizer ports (cl.getValue ("p"), ",");
152 a_service = new comm::RoundRobinDelivery ("Service_Arithmetic", true);
154 for (Tokenizer::const_iterator ii = ports.begin (), maxii = ports.end (); ii != maxii; ii ++) {
155 port = atoi (Tokenizer::data (ii));
156 a_service->attach (network.createServer (cl.getValue ("a"), port, true));
159 a_communicator.attach (a_service);
162 void RRClient::run ()
165 a_timeController.activate (a_sender);
167 a_communicator.accept ();
170 void MyCommunicator::eventReceiveMessage (ClientSocket&, const Message& message)
173 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
175 test::Response& response = a_responses.get ();
176 response.decode (message.getBody ());
178 const anna::Millisecond now = anna::functions::millisecond ();
179 const int delay = now - (Millisecond) response.initTime;
181 if (delay > 0 && isOk (response) == true) {
182 a_rxMessageCounter ++;
183 a_avgResponseTime += delay;
186 string msg = anna::functions::asString (
187 "%d %c %d = %d", response.x, response.op, response.y, response.result
189 msg += anna::functions::asText (" | Delay: ", delay);
190 Logger::information (msg, ANNA_FILE_LOCATION);
195 string msg = anna::functions::asString (
196 "Flip: %d %c %d = %d", response.x, response.op, response.y, response.result
198 msg += anna::functions::asText (" | Message: ", message.getBody ());
199 msg += anna::functions::asText (" | Delay: ", delay);
200 Logger::warning (msg, ANNA_FILE_LOCATION);
205 void MyCommunicator::eventBreakConnection (const Service* service)
208 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventBreakConnection", ANNA_FILE_LOCATION));
210 if (a_rxMessageCounter == 0)
213 comm::Communicator::eventBreakConnection (service);
215 if (service->isAvailable () == true) {
216 LOGNOTICE (Logger::notice (service->asString (), ANNA_FILE_LOCATION));
221 RRClient& app = static_cast <RRClient&> (anna::app::functions::getApp ());
222 string msg ("Tiempo medio respuesta: ");
223 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
225 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
226 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
227 Logger::notice (msg, ANNA_FILE_LOCATION);
229 cout << msg << endl << endl;
234 bool MyCommunicator::isOk (const test::Response& response)
237 if (response.op != '+' && response.op != '-' && response.op != '*' && response.op != '/')
242 switch (response.op) {
244 result = response.x + response.y;
247 result = response.x - response.y;
250 result = response.x * response.y;
253 result = (response.y != 0) ? (response.x / response.y): 0;
257 return result == response.result;
263 LOGMETHOD (TraceMethod tm (Logger::Local7, "Sender", "tick", ANNA_FILE_LOCATION));
265 Service* service = static_cast <RRClient&> (anna::comm::functions::getApp ()).getService ();
266 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
268 if (a_messageBySecond == 0)
269 throw RuntimeException ("Hay que indicar el numero de mensajes por segundo", ANNA_FILE_LOCATION);
272 if (a_errorCounter > 100) {
273 communicator->requestStop ();
274 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
278 test::Request& request = a_requests.get ();
280 for (int n = 0; n < a_messageBySecond && communicator->hasRequestedStop () == false; n ++) {
282 request.x = rand () % 1000;
283 request.y = rand () % 1000;
284 request.initTime = anna::functions::millisecond ();
287 service->send (request);
288 a_txMessageCounter ++;
290 catch (RuntimeException& ex) {