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/xml/DocumentMemory.hpp>
28 #include <anna/xml/Node.hpp>
29 #include <anna/xml/Parser.hpp>
31 #include <anna/timex/Engine.hpp>
32 #include <anna/timex/Clock.hpp>
34 #include <anna/http/Request.hpp>
35 #include <anna/http/Response.hpp>
36 #include <anna/http/Transport.hpp>
37 #include <anna/http/Handler.hpp>
39 static const Millisecond Resolution(250);
40 static const Millisecond Period(500);
41 static const Millisecond OneSecond(1000);
43 class Sender : public anna::timex::Clock {
47 void setMessageBySecond (const int messageBySecond) throw () { a_messageByTick = messageBySecond / (OneSecond / Period); }
49 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
52 struct Attribute { enum _v { ValueOne, ValueTwo, Operator, Time, Max }; };
57 int a_txMessageCounter;
58 http::Request a_httpRequest;
59 xml::Node* a_xmlRequest;
60 xml::Attribute* a_xmlAttributes [Attribute::Max];
62 /* Se invoca 4 veces por segundo */
63 bool tick () throw (RuntimeException);
66 class MyHandler : public http::Handler {
68 MyHandler () : http::Handler ("http_client::MyHandler") {;}
71 xml::DocumentMemory a_xmlRequest;
72 xml::Parser a_xmlParser;
74 void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
75 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
77 // static bool isOk (const test::Response& response) throw ();
80 class MyCommunicator : public Communicator {
82 MyCommunicator () : Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0) {;}
84 void count (const int delay) throw (RuntimeException);
87 int a_avgResponseTime;
88 int a_rxMessageCounter;
89 MyHandler a_httpHandler;
92 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
94 void eventBreakConnection (const ClientSocket&) throw ();
96 // Sustituye la redefinición de los siguientes métodos
97 using comm::Communicator::eventBreakConnection;
99 void eventBreakConnection (Server* server) throw () {
100 comm::Communicator::eventBreakConnection (server);
102 void eventBreakConnection (const Service* service) throw () {
103 comm::Communicator::eventBreakConnection (service);
108 class HeavyWIMS20Client : public anna::comm::Application {
110 HeavyWIMS20Client ();
112 Server* getServer () const throw () { return a_server; }
113 const Sender* getSender () const throw () { return &a_sender; }
116 MyCommunicator a_communicator;
117 anna::timex::Engine a_timeController;
121 void initialize () throw (RuntimeException);
122 void run () throw (RuntimeException);
127 int main (int argc, const char** argv)
129 CommandLine& commandLine (CommandLine::instantiate ());
130 HeavyWIMS20Client app;
135 commandLine.initialize (argv, argc);
136 commandLine.verify ();
138 Logger::setLevel (Logger::Information);
139 string traceFile ("client.");
140 traceFile += anna::functions::asString ((int) getpid ());
141 traceFile += ".trace";
142 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
146 catch (Exception& ex) {
147 cout << ex.asString () << endl;
153 HeavyWIMS20Client::HeavyWIMS20Client () :
154 Application ("http_client", "Cliente HTTP", "1.0"),
156 a_timeController (OneSecond, Resolution)
158 CommandLine& commandLine (CommandLine::instantiate ());
160 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
161 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
162 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
163 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
166 void HeavyWIMS20Client::initialize ()
167 throw (RuntimeException)
169 CommandLine& cl (CommandLine::instantiate ());
171 Network& network = Network::instantiate ();
173 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
174 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
176 if (cl.exists ("trace"))
177 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
180 void HeavyWIMS20Client::run ()
181 throw (RuntimeException)
183 a_timeController.activate (a_sender);
185 a_communicator.accept ();
188 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
189 throw (RuntimeException)
191 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
193 if (clientSocket.support (http::Transport::className ()) == false)
196 a_httpHandler.apply (clientSocket, message);
199 void MyCommunicator::count (const int delay)
200 throw (RuntimeException)
202 Guard guard (this, "MyCommunicator::count");
204 a_rxMessageCounter ++;
205 a_avgResponseTime += delay;
208 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
211 if (a_rxMessageCounter == 0)
215 HeavyWIMS20Client& app = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ());
216 string msg ("Tiempo medio respuesta: ");
217 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
219 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
220 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
221 Logger::notice (msg, ANNA_FILE_LOCATION);
223 cout << msg << endl << endl;
226 comm::Communicator::eventBreakConnection (clientSocket);
229 Sender::Sender () : Clock ("Sender", Period),
233 a_txMessageCounter (0)
235 a_httpRequest.setMethod (http::Method::Type::Get);
236 a_httpRequest.setURI ("http_xmlclient.p");
239 * Crea el documento XML que usaremos para codificar la respuesta y
240 * pre-localiza los objetos sobre los que tendrá que actuar
242 a_xmlRequest = new xml::Node ("Request");
243 a_xmlAttributes [Attribute::ValueOne] = a_xmlRequest->createAttribute ("ValueOne", 0);
244 a_xmlAttributes [Attribute::ValueTwo] = a_xmlRequest->createAttribute ("ValueTwo", 0);
245 a_xmlAttributes [Attribute::Operator] = a_xmlRequest->createAttribute ("Operator", 0);
246 a_xmlAttributes [Attribute::Time] = a_xmlRequest->createAttribute ("Millisecond", 0);
250 throw (RuntimeException)
252 Server* server = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ()).getServer ();
253 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
255 if (a_errorCounter > 100) {
256 communicator->requestStop ();
257 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
261 for (int n = 0; n < a_messageByTick && communicator->hasRequestedStop () == false; n ++) {
262 a_xmlAttributes [Attribute::ValueOne]->setValue (rand () % 1000);
263 a_xmlAttributes [Attribute::ValueTwo]->setValue (rand () % 1000);
264 a_xmlAttributes [Attribute::Operator]->setValue ("+");
265 a_xmlAttributes [Attribute::Time]->setValue (anna::functions::millisecond ());
268 a_httpRequest.setBody (a_xmlRequest);
269 server->send (a_httpRequest);
270 a_txMessageCounter ++;
272 catch (RuntimeException& ex) {
282 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
283 throw (RuntimeException)
285 if (response.getStatusCode () != 200)
288 a_xmlRequest.initialize (response.getBody ());
290 const xml::Node* root = a_xmlRequest.parse ();
292 const anna::Millisecond now = anna::functions::millisecond ();
293 const anna::Millisecond past(root->getAttribute ("Time")->getIntegerValue ());
295 const int delay = now - past;
299 string msg = a_xmlRequest.getContentAsCString ();
300 msg += anna::functions::asText (" | Delay: ", delay);
301 Logger::warning (msg, ANNA_FILE_LOCATION);
306 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (delay);