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 Ejemplo de uso del sistema de receiveres, que son capaces de tratar N peticiones de forma
15 totalmetne simultanea en caso de estar en un entorno MT.
17 Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de
18 retardo aplicados a cada contestacion.
20 Los clientes pueden ser: client.p o kclient.p
24 #include <anna/core/core.hpp>
25 #include <anna/comm/comm.hpp>
27 #include <anna/xml/Node.hpp>
28 #include <anna/xml/Attribute.hpp>
30 #include <anna/app/functions.hpp>
32 #include <anna/test/Request.hpp>
33 #include <anna/test/Response.hpp>
34 #include <anna/test/Communicator.hpp>
39 class MyCommunicator : public test::Communicator {
41 MyCommunicator (Communicator::WorkMode::_v workMode) : test::Communicator () {;}
44 class MyReceiver : public Receiver {
46 static const char* className () throw () { return "MyReceiver"; }
51 MyCommunicator* a_communicator;
53 MyReceiver () : Receiver ("MyReceiver") { ; }
54 void initialize () throw (RuntimeException);
55 void apply (comm::ClientSocket &, const Message&) throw (RuntimeException);
57 friend class Allocator <MyReceiver>;
60 class ArithmeticServer : public comm::Application {
63 ~ArithmeticServer () { delete a_communicator; }
66 MyCommunicator* a_communicator;
67 ReceiverFactoryImpl <MyReceiver> a_receiverFactory;
68 comm::ServerSocket* a_serverSocket;
70 void initialize () throw (RuntimeException);
71 void run () throw (RuntimeException);
72 xml::Node* asXML (xml::Node* app) const throw ();
73 void signalTerminate () throw (RuntimeException);
77 using namespace anna::comm;
79 int main (int argc, const char** argv)
81 CommandLine& commandLine (CommandLine::instantiate ());
87 commandLine.initialize (argv, argc);
88 commandLine.verify ();
90 Logger::setLevel (Logger::Debug);
91 string traceFile ("server.");
92 traceFile += anna::functions::asString ((int) getpid ());
93 traceFile += ".trace";
94 Logger::initialize ("arithmeticServer", new TraceWriter (traceFile.c_str (),4096000));
98 catch (Exception& ex) {
99 cout << ex.asString () << endl;
105 ArithmeticServer::ArithmeticServer () :
106 Application ("arithmeticServer", "Servidor de operaciones (iRS)", "1.0"),
107 a_communicator (NULL)
109 CommandLine& commandLine (CommandLine::instantiate ());
111 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
112 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
113 commandLine.add ("d", CommandLine::Argument::Mandatory, "Retardo aplicado a la contestacio");
114 commandLine.add ("maxpending", CommandLine::Argument::Optional, "Numero maximo de bytes en la cola de entrada");
115 commandLine.add ("limit", CommandLine::Argument::Mandatory, "% de ocupacion que permitimos");
116 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccion", false);
117 commandLine.add ("n", CommandLine::Argument::Optional, "Numero de mensajes a servir", true);
118 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
119 commandLine.add ("clone", CommandLine::Argument::Optional, "Aplica el metodo de clonado en el tratamiento de mensajes", false);
120 commandLine.add ("chunksize", CommandLine::Argument::Optional, "Tamano del chunk de lectura");
123 //-----------------------------------------------------------------------------------------
124 // Inicializa el servidor de sockets.
125 //-----------------------------------------------------------------------------------------
126 void ArithmeticServer::initialize ()
127 throw (RuntimeException)
129 LOGMETHOD (TraceMethod tm ("ArithmeticServer", "initialize", ANNA_FILE_LOCATION));
131 CommandLine& cl (CommandLine::instantiate ());
133 int port = cl.getIntegerValue ("p");
134 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
136 if (cl.exists ("trace"))
137 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
139 if (cl.exists ("chunksize"))
140 comm::Communicator::setReceivingChunkSize (cl.getIntegerValue ("chunksize"));
142 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"));
143 a_serverSocket->setCategory (777);
144 a_serverSocket->setReceiverFactory (a_receiverFactory);
146 comm::Communicator::WorkMode::_v workMode = (cl.exists ("clone")) ? comm::Communicator::WorkMode::Clone: comm::Communicator::WorkMode::Single;
148 a_communicator = new MyCommunicator (workMode);
151 //-----------------------------------------------------------------------------------------
152 // Atiende las peticiones.
153 // Cuando hay un nuevo mensaje invocar�a Communicator::eventReceiveMessage
154 //-----------------------------------------------------------------------------------------
155 void ArithmeticServer::run ()
156 throw (RuntimeException)
158 LOGMETHOD (TraceMethod tm ("ArithmeticServer", "run", ANNA_FILE_LOCATION));
160 CommandLine& cl (CommandLine::instantiate ());
162 a_communicator->attach (a_serverSocket);
163 a_communicator->setDelay ((Millisecond)cl.getIntegerValue ("d"));
165 if (cl.exists ("n") == true)
166 a_communicator->setMaxMessage (cl.getIntegerValue ("n"));
168 CongestionController& ccgg = CongestionController::instantiate ();
170 ccgg.setLimit (cl.getIntegerValue ("limit"));
172 if (cl.exists ("maxpending"))
173 ccgg.setMaxPendingBytes (cl.getIntegerValue ("maxpending"));
175 a_communicator->accept ();
178 xml::Node* ArithmeticServer::asXML (xml::Node* app) const
181 xml::Node* node = app::Application::asXML (app);
183 node->createAttribute ("MaxMessage", a_communicator->getMaxMessage ());
184 node->createAttribute ("Message", a_communicator->getMessage ());
189 void ArithmeticServer::signalTerminate ()
190 throw (RuntimeException)
192 a_communicator->terminate ();
193 comm::Application::signalTerminate ();
196 void MyReceiver::initialize ()
197 throw (RuntimeException)
199 a_communicator = app::functions::component <MyCommunicator> (ANNA_FILE_LOCATION);
202 void MyReceiver::apply (ClientSocket& clientSocket, const Message& message)
203 throw (RuntimeException)
205 LOGMETHOD (TraceMethod tm ("MyReceiver", "apply", ANNA_FILE_LOCATION));
207 if (a_communicator->canContinue (clientSocket) == false)
210 a_request.decode (message.getBody ());
212 a_communicator->delay ();
214 a_response.x = a_request.x;
215 a_response.y = a_request.y;
216 a_response.initTime = a_request.initTime;
218 switch (a_response.op = a_request.op) {
220 a_response.result = a_request.x + a_request.y;
223 a_response.result = a_request.x - a_request.y;
226 a_response.result = a_request.x * a_request.y;
229 a_response.result = (a_request.y != 0) ? (a_request.x / a_request.y): 0;
234 string msg = anna::functions::asString ("%d %c %d = %d", a_request.x, a_request.op, a_request.y, a_response.result);
235 msg += anna::functions::asText (" | InitTime: ", a_response.initTime);
236 Logger::information (msg, ANNA_FILE_LOCATION);
240 clientSocket.send (a_response);
242 catch (Exception& ex) {