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 //
9 #ifndef anna_comm_comm_hpp
10 #define anna_comm_comm_hpp
14 Proporciona las clases necesarias para la comunicacion entre procesos.
16 A continuacion presentamos el codigo de ejemplo de un servidor aritmetico. Recibe dos operadores y una
17 operacion (+,-,*,/) y devuelve el resultado de la operacion. Para estudiar los sistemas de control de
18 congestion hemos incorporado la posibilidad de que el servidor espere un numero de segundo indeterminado
19 antes de dar la respuesta.
26 #include <anna/comm/h>
28 #include <test.Request.h>
29 #include <test.Response.h>
34 //-----------------------------------------------------------------------------------------
35 // Define el comunicador de nuestra aplicacin.
37 // Las peticiones y respuestas van codificadas mediante un comm::Codec pero podriamos
38 // haber utilizado cualquier otro medio de codificacin ya que la capa de transporte
39 // es totalmente independiente del contenido del mensaje.
41 // De cara a la capa de transporte lo unico que importa es el cliente y el servidor
42 // codifiquen/decodifiquen de la misma forma.
43 //-----------------------------------------------------------------------------------------
44 class MyCommunicator : public comm::Communicator {
48 void setDelay (const Millisecond &delay) throw () { a_delay = delay; }
55 void eventReceiveMessage (comm::ClientSocket &, const DataBlock& data)
56 throw (RuntimeException);
59 class ArithmeticServer : public comm::Application {
64 MyCommunicator a_communicator;
65 comm::ServerSocket* a_serverSocket;
67 void initialize () throw (RuntimeException);
68 void run () throw (RuntimeException);
72 using namespace anna::comm;
74 int main (int argc, const char** argv)
76 CommandLine& commandLine (CommandLine::instantiate ());
82 commandLine.initialize (argv, argc);
83 commandLine.verify ();
85 Logger::setLevel (Logger::Debug);
86 Logger::initialize ("arithmeticServer", new anna::TraceWriter ("file.trace", 4048000));
90 catch (Exception& ex) {
91 cout << ex.asString () << endl;
97 ArithmeticServer::ArithmeticServer () :
98 Application ("arithmeticServer", "Servidor de operaciones aritmeticas", "1.0")
100 CommandLine& commandLine (CommandLine::instantiate ());
102 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
103 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
104 commandLine.add ("d", CommandLine::Argument::Mandatory, "Retardo aplicado a la contestacio");
105 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccin", false);
106 commandLine.add ("limit", CommandLine::Argument::Mandatory, "% de ocupacion que permitimos");
109 //-----------------------------------------------------------------------------------------
110 // Inicializa el servidor de sockets.
111 //-----------------------------------------------------------------------------------------
112 void ArithmeticServer::initialize ()
113 throw (RuntimeException)
115 CommandLine& cl (CommandLine::instantiate ());
117 int port = cl.getIntegerValue ("p");
118 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
120 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"));
123 //-----------------------------------------------------------------------------------------
124 // Atiende las peticiones.
125 // Cuando hay un nuevo mensaje invocar�a Communicator::eventReceiveMessage
126 //-----------------------------------------------------------------------------------------
127 void ArithmeticServer::run ()
128 throw (RuntimeException)
130 CommandLine& cl (CommandLine::instantiate ());
132 a_communicator.attach (a_serverSocket);
133 a_communicator.setDelay (cl.getIntegerValue ("d"));
135 CongestionController::instantiate ().setLimit (cl.getIntegerValue ("limit"));
137 a_communicator.accept ();
140 //-----------------------------------------------------------------------------------------
141 // Manejador de peticiones.
142 // Calcular�la operacin solicitada y devolver�el resultado.
144 // clientSocket: Socket cliente por el que podemos responder a la peticin.
145 // transport: Instancia del transporto que ha interpretado el mensaje (getMessage).
146 //-----------------------------------------------------------------------------------------
147 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const DataBlock& data)
148 throw (RuntimeException)
150 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
152 static int messageCounter = 0;
153 static int successCounter = 0;
157 CongestionController& congestionController = CongestionController::instantiate ();
161 if (congestionController.getAdvice (clientSocket) == CongestionController::Advice::Discard)
166 int random = rand () % (a_delay / 10);
167 int sign = rand () % 2;
172 anna::functions::sleep (a_delay + random);
174 a_request.decode (data);
176 a_response.x = a_request.x;
177 a_response.y = a_request.y;
179 switch (a_response.op = a_request.op) {
181 a_response.result = a_request.x + a_request.y;
184 a_response.result = a_request.x - a_request.y;
187 a_response.result = a_request.x * a_request.y;
190 a_response.result = (a_request.y != 0) ? (a_request.x / a_request.y): 0;
195 string msg = anna::functions::asString (
196 "%d %c %d = %d", a_request.x, a_request.op, a_request.y, a_response.result
198 Logger::debug (msg, ANNA_FILE_LOCATION);
202 clientSocket.send (a_response.code ());
204 catch (Exception& ex) {
210 El siguiente ejemplo muestra un cliente correspondiente al servidor anterior, que lanza un numero
211 determinado de peticiones por segundo.
219 #include <anna/comm/h>
221 #include <anna.timex.Engine.h>
222 #include <anna.timex.Clock.h>
224 #include <test.Response.h>
225 #include <test.Request.h>
227 class Sender : public timex::Clock {
229 Sender () : Clock ("Sender", 250), a_messageBySecond (0), a_nquarter (0) {;}
231 void setMessageBySecond (const int messageBySecond) throw () { a_messageBySecond = messageBySecond; }
234 int a_messageBySecond;
236 test::Request a_request;
238 void tick () throw (RuntimeException);
241 //-----------------------------------------------------------------------------------------
242 // Define el comunicador de nuestra aplicacin.
244 // Las peticiones y respuestas van codificadas mediante un comm::Codec pero podriamos
245 // haber utilizado cualquier otro medio de codificacin ya que la capa de transporte
246 // es totalmente independiente del contenido del mensaje.
247 //-----------------------------------------------------------------------------------------
248 class MyCommunicator : public Communicator {
250 MyCommunicator () : Communicator () {;}
253 test::Response a_response;
255 void eventReceiveMessage (ClientSocket &, const DataBlock&)
256 throw (RuntimeException);
259 class HeavyClient : public anna::comm::Application {
263 Server* getServer () const throw () { return a_server; }
266 MyCommunicator a_communicator;
267 timex::Engine a_timeController;
271 void initialize () throw (RuntimeException);
272 void run () throw (RuntimeException);
277 int main (int argc, const char** argv)
279 CommandLine& commandLine (CommandLine::instantiate ());
285 commandLine.initialize (argv, argc);
286 commandLine.verify ();
288 Logger::setLevel (Logger::Debug);
289 Logger::initialize ("arithmeticClient", new TraceWriter ("file.trace", 1048000));
293 catch (Exception& ex) {
294 cout << ex.asString () << endl;
300 HeavyClient::HeavyClient () :
301 Application ("arithmeticClient", "Cliente de operaciones aritmeticas", "1.0"),
303 a_timeController ((Millisecond)10000, (Millisecond)250)
305 CommandLine& commandLine (CommandLine::instantiate ());
307 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que el servidor atiende respuestas.");
308 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP Puerto en el que el servidor atiende respuestas.");
309 commandLine.add ("n", CommandLine::Argument::Mandatory, "Numero de mensajes por segundo");
313 //-----------------------------------------------------------------------------------------
314 // Inicializa las conexiones usadas por la aplicacin.
316 // Primero establece los datos para la conexin con el servidor aritm�ico y luego
317 // establece los datos del socket servidor necesario para atender respuestas y aceptar
318 // nuevas conexiones de procesos clientes (que no ser�el caso).
319 // Configura el men para que trabaje con el comunicador de esta aplicacin.
320 //-----------------------------------------------------------------------------------------
321 void HeavyClient::initialize ()
322 throw (RuntimeException)
324 CommandLine& cl (CommandLine::instantiate ());
326 Network& network = Network::instantiate ();
328 Host* host = network.find ("host000");
329 host->assign (network.find (Device::asAddress (cl.getValue ("a"))));
330 a_server = host->createServer ("rawServer", cl.getIntegerValue ("p"), true);
331 a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
334 //-----------------------------------------------------------------------------------------
335 // Activa el reloj que dara el pulso para enviar los mensajes al servidor y comienza a
336 // atender las peticiones.
337 //-----------------------------------------------------------------------------------------
338 void HeavyClient::run ()
339 throw (RuntimeException)
341 a_timeController.activate (a_sender);
343 a_communicator.accept ();
346 //-----------------------------------------------------------------------------------------
347 // Manejador de respuesta.
349 // clientSocket: Socket cliente por el que podemos responder a la peticin.
350 // transport: Instancia del transporto que ha interpretado el mensaje (getMessage).
351 //-----------------------------------------------------------------------------------------
352 void MyCommunicator::eventReceiveMessage (ClientSocket&, const DataBlock& data)
353 throw (RuntimeException)
355 a_response.decode (data);
357 string msg = anna::functions::asString (
358 "%d %c %d = %d", a_response.x, a_response.op, a_response.y, a_response.result
360 Logger::information (msg, ANNA_FILE_LOCATION);
364 throw (RuntimeException)
366 Server* server = static_cast <HeavyClient&> (anna::app::functions::getApp ()).getServer ();
367 Communicator* communicator = anna::app::functions::component <Communicator> (ANNA_FILE_LOCATION);
369 int maxn = a_messageBySecond / 4;
371 if (++ a_nquarter == 4) {
372 maxn += a_messageBySecond % 4;
379 maxn = rand () % maxn;
381 for (int n = 0; n < maxn; n ++) {
383 a_request.x = rand () % 1000;
384 a_request.y = rand () % 1000;
387 server->send (a_request.code ());
389 catch (RuntimeException& ex) {
398 El ejecutable debera enlazarse con las librerias:
404 El <b>Packet Header</b> es anna/comm/h
410 #include <anna/comm/Application.hpp>
411 #include <anna/comm/Buffer.hpp>
412 #include <anna/comm/ClientSocket.hpp>
413 #include <anna/comm/Codec.hpp>
414 #include <anna/comm/Communicator.hpp>
415 #include <anna/comm/CongestionController.hpp>
416 #include <anna/comm/DatagramSocket.hpp>
417 #include <anna/comm/Device.hpp>
418 #include <anna/comm/Delivery.hpp>
419 #include <anna/comm/DirectTransport.hpp>
420 #include <anna/comm/Host.hpp>
421 #include <anna/comm/LargeBinaryCodec.hpp>
422 #include <anna/comm/LiteTransport.hpp>
423 #include <anna/comm/Message.hpp>
424 #include <anna/comm/Network.hpp>
425 #include <anna/comm/INetAddress.hpp>
426 #include <anna/comm/Transport.hpp>
427 #include <anna/comm/Server.hpp>
428 #include <anna/comm/Service.hpp>
429 #include <anna/comm/ServerAllocator.hpp>
430 #include <anna/comm/ServerSocket.hpp>
431 #include <anna/comm/handler/BinderSocket.hpp>
432 #include <anna/comm/Service.hpp>
433 #include <anna/comm/Status.hpp>
434 #include <anna/comm/Variable.hpp>
435 #include <anna/comm/Receiver.hpp>
436 #include <anna/comm/ReceiverFactory.hpp>
437 #include <anna/comm/ReceiverFactoryImpl.hpp>
438 #include <anna/comm/RoundRobinDelivery.hpp>
439 #include <anna/comm/ByRangeDelivery.hpp>
440 #include <anna/comm/IndexedDelivery.hpp>
442 using namespace anna::comm;