1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
38 Realiza peticiones automaticas sobre el servidor HTTP de operaciones aritmeticas.
40 La cadencia de envio de mensajes se establece mediante un temporizador.
41 Los operadores se calculan de forma aleatoria.
43 El servidor de este cliente: http_server.p o http_rserver.p
51 #include <anna/core/core.hpp>
52 #include <anna/app/functions.hpp>
53 #include <anna/comm/comm.hpp>
55 #include <anna/xml/DocumentMemory.hpp>
56 #include <anna/xml/Node.hpp>
58 #include <anna/timex/Engine.hpp>
59 #include <anna/timex/Clock.hpp>
61 #include <anna/http/Request.hpp>
62 #include <anna/http/Response.hpp>
63 #include <anna/http/Transport.hpp>
64 #include <anna/http/Handler.hpp>
66 #include <anna/http/wims20/ClientSide.hpp>
68 static const Millisecond Resolution(250);
69 static const Millisecond Period(500);
70 static const Millisecond OneSecond(1000);
72 class Sender : public anna::timex::Clock {
74 Sender () : Clock ("Sender", Period),
78 a_txMessageCounter (0),
81 a_httpRequest.setMethod (http::Method::Type::Get);
84 void setMessageBySecond (const int messageBySecond) throw () { a_messageByTick = messageBySecond / (OneSecond / Period); }
85 void setRequest (http::wims20::ClientSide* request) throw () { a_request = request; }
87 int getTxMessageCounter () const throw () { return a_txMessageCounter; }
93 int a_txMessageCounter;
94 http::Request a_httpRequest;
95 http::wims20::ClientSide* a_request;
97 /* Se invoca 4 veces por segundo */
98 bool tick () throw (RuntimeException);
101 class MyHandler : public http::Handler {
103 MyHandler () : http::Handler ("http_client::MyHandler") {;}
106 xml::DocumentMemory a_xmlResponse;
108 void evRequest (ClientSocket&, const http::Request&) throw (RuntimeException) {;}
109 void evResponse (ClientSocket&, const http::Response&) throw (RuntimeException);
111 // static bool isOk (const test::Response& response) throw ();
114 class MyCommunicator : public comm::Communicator {
116 MyCommunicator () : comm::Communicator (), a_avgResponseTime (0), a_rxMessageCounter (0) {;}
118 void count (const Millisecond delay) throw (RuntimeException);
120 // Sustituye la redefinición de los siguientes métodos
121 void eventBreakConnection (const comm::ClientSocket&) throw ();
122 using comm::Communicator::eventBreakConnection;
125 int a_avgResponseTime;
126 int a_rxMessageCounter;
127 MyHandler a_httpHandler;
129 void eventReceiveMessage (ClientSocket&, const Message&) throw (RuntimeException);
132 class HeavyWIMS20Client : public anna::comm::Application {
134 HeavyWIMS20Client ();
136 Server* getServer () const throw () { return a_server; }
137 const Sender* getSender () const throw () { return &a_sender; }
140 MyCommunicator a_communicator;
141 anna::timex::Engine a_timeController;
144 http::wims20::ClientSide* a_request;
146 void initialize () throw (RuntimeException);
147 void run () throw (RuntimeException);
152 int main (int argc, const char** argv)
154 CommandLine& commandLine (CommandLine::instantiate ());
155 HeavyWIMS20Client app;
160 commandLine.initialize (argv, argc);
161 commandLine.verify ();
163 Logger::setLevel (Logger::Information);
164 string traceFile ("client.");
165 traceFile += anna::functions::asString ((int) getpid ());
166 traceFile += ".trace";
167 Logger::initialize ("http_client", new TraceWriter (traceFile.c_str (),4096000));
171 catch (Exception& ex) {
172 cout << ex.asString () << endl;
178 HeavyWIMS20Client::HeavyWIMS20Client () :
179 Application ("http_client", "Cliente HTTP", "1.0"),
181 a_timeController (OneSecond, Resolution),
184 CommandLine& commandLine (CommandLine::instantiate ());
186 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
187 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
188 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
189 commandLine.add ("domain", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
190 commandLine.add ("path", CommandLine::Argument::Optional, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
191 commandLine.add ("service", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
192 commandLine.add ("guid", CommandLine::Argument::Mandatory, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
193 commandLine.add ("other", CommandLine::Argument::Optional, "http://domain-openapis/path-openapis/serviceID/guid/other_possible_levels?query_parameters");
194 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
197 void HeavyWIMS20Client::initialize ()
198 throw (RuntimeException)
200 CommandLine& cl (CommandLine::instantiate ());
202 Network& network = Network::instantiate ();
204 a_server = network.createServer (cl.getValue ("a"), cl.getIntegerValue ("p"), true, &http::Transport::getFactory ());
205 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
207 if (cl.exists ("trace"))
208 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
210 const char* domain = cl.getValue ("domain");
212 if (cl.exists ("path"))
213 a_request = new http::wims20::ClientSide (domain, cl.getValue ("path"));
215 a_request = new http::wims20::ClientSide (domain);
217 a_request->setServiceID (cl.getValue ("service"));
218 a_request->setGUID (cl.getValue ("guid"));
220 if (cl.exists ("other"))
221 a_request->addOtherLevel (cl.getValue ("other"));
223 a_sender.setRequest (a_request);
226 void HeavyWIMS20Client::run ()
227 throw (RuntimeException)
229 a_timeController.activate (a_sender);
231 a_communicator.accept ();
234 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
235 throw (RuntimeException)
237 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
239 if (clientSocket.support (http::Transport::className ()) == false)
242 a_httpHandler.apply (clientSocket, message);
245 void MyCommunicator::count (const Millisecond delay)
246 throw (RuntimeException)
248 Guard guard (this, "MyCommunicator::count");
250 a_rxMessageCounter ++;
251 a_avgResponseTime += delay;
254 void MyCommunicator::eventBreakConnection (const ClientSocket& clientSocket)
257 if (a_rxMessageCounter == 0) {
259 string msg ("MyCommunicator::eventBreakConnection | ");
260 msg += clientSocket.asString ();
261 Logger::warning (msg, ANNA_FILE_LOCATION);
267 HeavyWIMS20Client& app = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ());
268 string msg ("Tiempo medio respuesta: ");
269 msg += anna::functions::asString (a_avgResponseTime / a_rxMessageCounter);
271 msg += anna::functions::asText (" | Rx: ", a_rxMessageCounter);
272 msg += anna::functions::asText (" | Tx: ", app.getSender ()->getTxMessageCounter ());
273 Logger::notice (msg, ANNA_FILE_LOCATION);
275 cout << msg << endl << endl;
278 comm::Communicator::eventBreakConnection (clientSocket);
282 throw (RuntimeException)
284 Server* server = static_cast <HeavyWIMS20Client&> (anna::app::functions::getApp ()).getServer ();
285 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
287 if (a_errorCounter > 50) {
288 communicator->requestStop ();
289 Logger::warning ("Terminado por errores continuos en la conexion", ANNA_FILE_LOCATION);
293 for (int n = 0; n < a_messageByTick && communicator->hasRequestedStop () == false; n ++) {
294 a_request->setParameter ("Operator", "a");
295 a_request->setParameter ("ValueOne", rand () % 1000);
296 a_request->setParameter ("ValueTwo", rand () % 1000);
297 a_request->setParameter ("Time", anna::functions::millisecond ());
300 a_request->codeOn (a_httpRequest);
301 server->send (a_httpRequest);
302 a_txMessageCounter ++;
304 catch (RuntimeException& ex) {
314 void MyHandler::evResponse (ClientSocket& clientSocket, const http::Response& response)
315 throw (RuntimeException)
317 TraceMethod tm ("MyHandler", "evResponse", ANNA_FILE_LOCATION);
319 if (response.getStatusCode () != 200)
322 // El servidor implementado en Java retornará un 500 cuando alcanze el nº máximo de mensajes.
323 if (response.getStatusCode () == 500) {
325 string msg (" MyHandler::evResponse | ");
326 msg += response.asString ();
327 msg += " | Servidor java notifica fin de la prueba.";
328 Logger::debug (msg, ANNA_FILE_LOCATION);
330 eventBreakConnection (clientSocket);
334 a_xmlResponse.initialize (response.getBody ());
336 const xml::Node* root = a_xmlResponse.parse ();
338 const anna::Millisecond now = anna::functions::millisecond ();
339 const anna::Millisecond past(root->getAttribute ("Time")->getIntegerValue ());
341 const int delay = now - past;
345 string msg = a_xmlResponse.getContentAsCString ();
346 msg += anna::functions::asText (" | Delay: ", delay);
347 Logger::warning (msg, ANNA_FILE_LOCATION);
352 app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION)->count (Millisecond(delay));