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 Ejemplo de programa servidor. Atiende peticiones aritmeticas, el protocolo de transporte
11 sera el comm::Transport y el contenido del mensaje sera el resutaldo de un comm::Codec con los
12 (x, y, op) -> El resultado sera estos tres componente mas result.
14 Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de
15 retardo aplicados a cada contestacion.
17 Los clientes pueden ser: client o kClient
22 #include <anna/core/core.hpp>
23 #include <anna/comm/comm.hpp>
25 #include <anna/xml/Node.hpp>
26 #include <anna/xml/Attribute.hpp>
28 #include <anna/test/Request.hpp>
29 #include <anna/test/Response.hpp>
30 #include <anna/test/Communicator.hpp>
40 class MyCommunicator : public test::Communicator {
43 a_contexts ("Contexts")
47 ThreadData <Context> a_contexts;
49 void eventReceiveMessage (comm::ClientSocket&, const Message&) throw (RuntimeException);
52 class ArithmeticServer : public comm::Application {
57 MyCommunicator a_communicator;
58 comm::ServerSocket* a_serverSocket;
60 void initialize () throw (RuntimeException);
61 void run () throw (RuntimeException);
62 xml::Node* asXML (xml::Node* app) const throw ();
66 using namespace anna::comm;
68 int main (int argc, const char** argv)
70 CommandLine& commandLine (CommandLine::instantiate ());
78 commandLine.initialize (argv, argc);
79 commandLine.verify ();
81 Logger::setLevel (Logger::Debug);
82 string traceFile ("server.");
83 traceFile += anna::functions::asString ((int) getpid ());
84 traceFile += ".trace";
85 Logger::initialize ("arithmeticServer", new TraceWriter (traceFile.c_str (),4096000));
89 catch (Exception& ex) {
90 cout << ex.asString () << endl;
96 ArithmeticServer::ArithmeticServer () :
97 Application ("arithmeticServer", "Servidor de operaciones aritm�icas", "1.0")
99 CommandLine& commandLine (CommandLine::instantiate ());
101 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
102 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
103 commandLine.add ("d", CommandLine::Argument::Mandatory, "Retardo aplicado a la contestacion");
104 commandLine.add ("limit", CommandLine::Argument::Mandatory, "% de ocupacion que permitimos");
105 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccin", false);
106 commandLine.add ("n", CommandLine::Argument::Optional, "Numero de mensajes a servir", true);
107 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
110 //-----------------------------------------------------------------------------------------
111 // Inicializa el servidor de sockets.
112 //-----------------------------------------------------------------------------------------
113 void ArithmeticServer::initialize ()
114 throw (RuntimeException)
116 CommandLine& cl (CommandLine::instantiate ());
118 int port = cl.getIntegerValue ("p");
119 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
121 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"));
122 a_serverSocket->setCategory (777);
125 //-----------------------------------------------------------------------------------------
126 // Atiende las peticiones.
127 // Cuando hay un nuevo mensaje invocar�a Communicator::eventReceiveMessage
128 //-----------------------------------------------------------------------------------------
129 void ArithmeticServer::run ()
130 throw (RuntimeException)
132 CommandLine& cl (CommandLine::instantiate ());
134 a_communicator.attach (a_serverSocket);
135 a_communicator.setDelay ((Millisecond)cl.getIntegerValue ("d"));
137 if (cl.exists ("n") == true)
138 a_communicator.setMaxMessage (cl.getIntegerValue ("n"));
140 if (cl.exists ("trace"))
141 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
143 CongestionController::instantiate ().setLimit (cl.getIntegerValue ("limit"));
145 a_communicator.accept ();
148 xml::Node* ArithmeticServer::asXML (xml::Node* app) const
151 xml::Node* node = app::Application::asXML (app);
153 node->createAttribute ("MaxMessage", a_communicator.getMaxMessage ());
154 node->createAttribute ("Message", a_communicator.getMessage ());
159 //-----------------------------------------------------------------------------------------
160 // Manejador de peticiones.
161 // Calcular�la operacin solicitada y devolver�el resultado.
163 // clientSocket: Socket cliente por el que podemos responder a la peticin.
164 // transport: Instancia del transporto que ha interpretado el mensaje (getMessage).
165 //-----------------------------------------------------------------------------------------
166 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
167 throw (RuntimeException)
169 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
171 if (canContinue (clientSocket) == false)
176 Context& context = a_contexts.get ();
177 Request& request (context.request);
178 Response& response (context.response);
180 request.decode (message.getBody ());
182 response.x = request.x;
183 response.y = request.y;
184 response.initTime = request.initTime;
186 switch (response.op = request.op) {
188 response.result = request.x + request.y;
191 response.result = request.x - request.y;
194 response.result = request.x * request.y;
197 response.result = (request.y != 0) ? (request.x / request.y): 0;
202 string msg = anna::functions::asString ("%d %c %d = %d", request.x, request.op, request.y, response.result);
203 msg += anna::functions::asText (" | InitTime: ", response.initTime);
204 Logger::information (msg, ANNA_FILE_LOCATION);
208 clientSocket.send (response);
210 catch (Exception& ex) {