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>
30 #include <anna/timex/Engine.hpp>
31 #include <anna/timex/Clock.hpp>
33 #include <anna/http/Request.hpp>
34 #include <anna/http/Response.hpp>
35 #include <anna/http/Transport.hpp>
36 #include <anna/http/Handler.hpp>
38 #include <anna/http/wims20/ClientSide.hpp>
40 static const Millisecond Resolution(250);
41 static const Millisecond Period(500);
42 static const Millisecond OneSecond(1000);
44 class Sender : public anna::timex::Clock {
46 Sender () : Clock ("Sender", Period),
50 a_txMessageCounter (0),
53 a_httpRequest.setMethod (http::Method::Type::Get);
56 void setMessageBySecond (const int messageBySecond) throw () { a_messageByTick = messageBySecond / (OneSecond / Period); }
57 void setRequest (http::wims20::ClientSide* request) throw () { a_request = request; }
59 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
65 int a_txMessageCounter;
66 http::Request a_httpRequest;
67 http::wims20::ClientSide* a_request;
69 /* Se invoca 4 veces por segundo */
70 bool tick () throw (RuntimeException);
73 class MyHandler : public http::Handler {
75 MyHandler () : http::Handler ("http_client::MyHandler") {;}
78 xml::DocumentMemory a_xmlResponse;
80 void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
81 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
83 // static bool isOk (const test::Response& response) throw ();
86 class MyCommunicator : public comm::Communicator {
88 MyCommunicator () : comm::Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0) {;}
90 void count (const Millisecond delay) throw (RuntimeException);
92 // Sustituye la redefinición de los siguientes métodos
93 void eventBreakConnection (const comm::ClientSocket&) throw ();
94 using comm::Communicator::eventBreakConnection;
97 int a_avgResponseTime;
98 int a_rxMessageCounter;
99 MyHandler a_httpHandler;
101 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
104 class HeavyWIMS20Client : public anna::comm::Application {
106 HeavyWIMS20Client ();
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;
116 http::wims20::ClientSide* a_request;
118 void initialize () throw (RuntimeException);
119 void run () throw (RuntimeException);
124 int main (int argc, const char** argv)
126 CommandLine& commandLine (CommandLine::instantiate ());
127 HeavyWIMS20Client app;
132 commandLine.initialize (argv, argc);
133 commandLine.verify ();
135 Logger::setLevel (Logger::Information);
136 string traceFile ("client.");
137 traceFile += anna::functions::asString ((int) getpid ());
138 traceFile += ".trace";
139 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
143 catch (Exception& ex) {
144 cout << ex.asString () << endl;
150 HeavyWIMS20Client::HeavyWIMS20Client () :
151 Application ("http_client", "Cliente HTTP", "1.0"),
153 a_timeController (OneSecond, Resolution),
156 CommandLine& commandLine (CommandLine::instantiate ());
158 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
159 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
160 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
161 commandLine.add ("domain", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
162 commandLine.add ("path", CommandLine::Argument::Optional, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
163 commandLine.add ("service", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
164 commandLine.add ("guid", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
165 commandLine.add ("other", CommandLine::Argument::Optional, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
166 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
169 void HeavyWIMS20Client::initialize ()
170 throw (RuntimeException)
172 CommandLine& cl (CommandLine::instantiate ());
174 Network& network = Network::instantiate ();
176 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
177 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
179 if (cl.exists ("trace"))
180 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
182 const char* domain = cl.getValue ("domain");
184 if (cl.exists ("path"))
185 a_request = new http::wims20::ClientSide (domain, cl.getValue ("path"));
187 a_request = new http::wims20::ClientSide (domain);
189 a_request->setServiceID (cl.getValue ("service"));
190 a_request->setGUID (cl.getValue ("guid"));
192 if (cl.exists ("other"))
193 a_request->addOtherLevel (cl.getValue ("other"));
195 a_sender.setRequest (a_request);
198 void HeavyWIMS20Client::run ()
199 throw (RuntimeException)
201 a_timeController.activate (a_sender);
203 a_communicator.accept ();
206 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
207 throw (RuntimeException)
209 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
211 if (clientSocket.support (http::Transport::className ()) == false)
214 a_httpHandler.apply (clientSocket, message);
217 void MyCommunicator::count (const Millisecond delay)
218 throw (RuntimeException)
220 Guard guard (this, "MyCommunicator::count");
222 a_rxMessageCounter ++;
223 a_avgResponseTime += delay;
226 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
229 if (a_rxMessageCounter == 0) {
231 string msg ("MyCommunicator::eventBreakConnection | ");
232 msg += clientSocket.asString ();
233 Logger::warning (msg, ANNA_FILE_LOCATION);
239 HeavyWIMS20Client& app = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ());
240 string msg ("Tiempo medio respuesta: ");
241 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
243 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
244 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
245 Logger::notice (msg, ANNA_FILE_LOCATION);
247 cout << msg << endl << endl;
250 comm::Communicator::eventBreakConnection (clientSocket);
254 throw (RuntimeException)
256 Server* server = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ()).getServer ();
257 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
259 if (a_errorCounter > 50) {
260 communicator->requestStop ();
261 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
265 for (int n = 0; n < a_messageByTick && communicator->hasRequestedStop () == false; n ++) {
266 a_request->setParameter ("Operator", "a");
267 a_request->setParameter ("ValueOne", rand () % 1000);
268 a_request->setParameter ("ValueTwo", rand () % 1000);
269 a_request->setParameter ("Time", anna::functions::millisecond ());
272 a_request->codeOn (a_httpRequest);
273 server->send (a_httpRequest);
274 a_txMessageCounter ++;
276 catch (RuntimeException& ex) {
286 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
287 throw (RuntimeException)
289 TraceMethod tm ("MyHandler", "evResponse", ANNA_FILE_LOCATION);
291 if (response.getStatusCode () != 200)
294 // El servidor implementado en Java retornará un 500 cuando alcanze el nº máximo de mensajes.
295 if (response.getStatusCode () == 500) {
297 string msg (" MyHandler::evResponse | ");
298 msg += response.asString ();
299 msg += " | Servidor java notifica fin de la prueba.";
300 Logger::debug (msg, ANNA_FILE_LOCATION);
302 eventBreakConnection (clientSocket);
306 a_xmlResponse.initialize (response.getBody ());
308 const xml::Node* root = a_xmlResponse.parse ();
310 const anna::Millisecond now = anna::functions::millisecond ();
311 const anna::Millisecond past(root->getAttribute ("Time")->getIntegerValue ());
313 const int delay = now - past;
317 string msg = a_xmlResponse.getContentAsCString ();
318 msg += anna::functions::asText (" | Delay: ", delay);
319 Logger::warning (msg, ANNA_FILE_LOCATION);
324 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (Millisecond(delay));