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 Ejemplo de programa servidor. Atiende peticiones aritmeticas, el protocolo de transporte
39 sera el comm::Transport y el contenido del mensaje sera el resutaldo de un comm::Codec con los
40 (x, y, op) -> El resultado sera estos tres componente mas result.
42 Para poder probar el sistema de congestion se puede indicar un numero de milisegundos de
43 retardo aplicados a cada contestacion.
45 Los clientes pueden ser: client o kClient
50 #include <anna/core/core.hpp>
51 #include <anna/comm/comm.hpp>
53 #include <anna/xml/Node.hpp>
54 #include <anna/xml/Attribute.hpp>
56 #include <anna/test/Request.hpp>
57 #include <anna/test/Response.hpp>
58 #include <anna/test/Communicator.hpp>
68 class MyCommunicator : public test::Communicator {
71 a_contexts ("Contexts")
75 ThreadData <Context> a_contexts;
77 void eventReceiveMessage (comm::ClientSocket&, const Message&) throw (RuntimeException);
80 class ArithmeticServer : public comm::Application {
85 MyCommunicator a_communicator;
86 comm::ServerSocket* a_serverSocket;
88 void initialize () throw (RuntimeException);
89 void run () throw (RuntimeException);
90 xml::Node* asXML (xml::Node* app) const throw ();
94 using namespace anna::comm;
96 int main (int argc, const char** argv)
98 CommandLine& commandLine (CommandLine::instantiate ());
106 commandLine.initialize (argv, argc);
107 commandLine.verify ();
109 Logger::setLevel (Logger::Debug);
110 string traceFile ("server.");
111 traceFile += anna::functions::asString ((int) getpid ());
112 traceFile += ".trace";
113 Logger::initialize ("arithmeticServer", new TraceWriter (traceFile.c_str (),4096000));
117 catch (Exception& ex) {
118 cout << ex.asString () << endl;
124 ArithmeticServer::ArithmeticServer () :
125 Application ("arithmeticServer", "Servidor de operaciones aritm�icas", "1.0")
127 CommandLine& commandLine (CommandLine::instantiate ());
129 commandLine.add ("p", CommandLine::Argument::Mandatory, "Puerto en el que atender peticiones");
130 commandLine.add ("a", CommandLine::Argument::Mandatory, "Direccin IP en la que atender");
131 commandLine.add ("d", CommandLine::Argument::Mandatory, "Retardo aplicado a la contestacion");
132 commandLine.add ("limit", CommandLine::Argument::Mandatory, "% de ocupacion que permitimos");
133 commandLine.add ("r", CommandLine::Argument::Optional, "Indicador de reuso de direccin", false);
134 commandLine.add ("n", CommandLine::Argument::Optional, "Numero de mensajes a servir", true);
135 commandLine.add ("trace", CommandLine::Argument::Optional, "Nivel de trazas (debug,warning, error,...)");
138 //-----------------------------------------------------------------------------------------
139 // Inicializa el servidor de sockets.
140 //-----------------------------------------------------------------------------------------
141 void ArithmeticServer::initialize ()
142 throw (RuntimeException)
144 CommandLine& cl (CommandLine::instantiate ());
146 int port = cl.getIntegerValue ("p");
147 const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
149 a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"));
150 a_serverSocket->setCategory (777);
153 //-----------------------------------------------------------------------------------------
154 // Atiende las peticiones.
155 // Cuando hay un nuevo mensaje invocar�a Communicator::eventReceiveMessage
156 //-----------------------------------------------------------------------------------------
157 void ArithmeticServer::run ()
158 throw (RuntimeException)
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 if (cl.exists ("trace"))
169 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
171 CongestionController::instantiate ().setLimit (cl.getIntegerValue ("limit"));
173 a_communicator.accept ();
176 xml::Node* ArithmeticServer::asXML (xml::Node* app) const
179 xml::Node* node = app::Application::asXML (app);
181 node->createAttribute ("MaxMessage", a_communicator.getMaxMessage ());
182 node->createAttribute ("Message", a_communicator.getMessage ());
187 //-----------------------------------------------------------------------------------------
188 // Manejador de peticiones.
189 // Calcular�la operacin solicitada y devolver�el resultado.
191 // clientSocket: Socket cliente por el que podemos responder a la peticin.
192 // transport: Instancia del transporto que ha interpretado el mensaje (getMessage).
193 //-----------------------------------------------------------------------------------------
194 void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const Message& message)
195 throw (RuntimeException)
197 LOGMETHOD (TraceMethod tm ("MyCommunicator", "eventReceiveMessage", ANNA_FILE_LOCATION));
199 if (canContinue (clientSocket) == false)
204 Context& context = a_contexts.get ();
205 Request& request (context.request);
206 Response& response (context.response);
208 request.decode (message.getBody ());
210 response.x = request.x;
211 response.y = request.y;
212 response.initTime = request.initTime;
214 switch (response.op = request.op) {
216 response.result = request.x + request.y;
219 response.result = request.x - request.y;
222 response.result = request.x * request.y;
225 response.result = (request.y != 0) ? (request.x / request.y): 0;
230 string msg = anna::functions::asString ("%d %c %d = %d", request.x, request.op, request.y, response.result);
231 msg += anna::functions::asText (" | InitTime: ", response.initTime);
232 Logger::information (msg, ANNA_FILE_LOCATION);
236 clientSocket.send (response);
238 catch (Exception& ex) {