Proporciona las clases necesarias para la comunicacion entre procesos.
A continuacion presentamos el codigo de ejemplo de un servidor aritmetico. Recibe dos operadores y una operacion (+,-,*,/) y devuelve el resultado de la operacion. Para estudiar los sistemas de control de congestion hemos incorporado la posibilidad de que el servidor espere un numero de segundo indeterminado antes de dar la respuesta.
#include <iostream>
#include <anna.h>
#include <anna/comm/h>
#include <test.Request.h>
#include <test.Response.h>
using namespace std;
public:
MyCommunicator () {;}
void setDelay (const Millisecond &delay) { a_delay = delay; }
private:
Millisecond a_delay;
void eventReceiveMessage (comm::ClientSocket &, const DataBlock& data)
noexcept(false);
};
class ArithmeticServer : public comm::Application {
public:
ArithmeticServer ();
private:
MyCommunicator a_communicator;
comm::ServerSocket* a_serverSocket;
void initialize () noexcept(false);
void run () noexcept(false);
};
using namespace std;
using namespace
anna::comm;
int main (int argc, const char** argv)
{
ArithmeticServer app;
srand (time (NULL));
try {
commandLine.initialize (argv, argc);
commandLine.verify ();
app.start ();
}
catch (Exception& ex) {
cout << ex.asString () << endl;
}
return 0;
}
ArithmeticServer::ArithmeticServer () :
Application ("arithmeticServer", "Servidor de operaciones aritmeticas", "1.0")
{
}
void ArithmeticServer::initialize ()
noexcept(false)
{
int port = cl.getIntegerValue ("p");
const comm::Device* device = Network::instantiate ().find (Device::asAddress (cl.getValue ("a")));
a_serverSocket = new ServerSocket (INetAddress (device, port), cl.exists ("r"));
}
void ArithmeticServer::run ()
noexcept(false)
{
a_communicator.attach (a_serverSocket);
a_communicator.setDelay (cl.getIntegerValue ("d"));
CongestionController::instantiate ().setLimit (cl.getIntegerValue ("limit"));
a_communicator.accept ();
}
void MyCommunicator::eventReceiveMessage (ClientSocket& clientSocket, const DataBlock& data)
noexcept(false)
{
static int messageCounter = 0;
static int successCounter = 0;
int value;
CongestionController& congestionController = CongestionController::instantiate ();
messageCounter ++;
if (congestionController.getAdvice (clientSocket) == CongestionController::Advice::Discard)
return;
successCounter ++;
int random = rand () % (a_delay / 10);
int sign = rand () % 2;
if (sign == 0)
random *= -1;
a_request.decode (data);
a_response.x = a_request.x;
a_response.y = a_request.y;
switch (a_response.op = a_request.op) {
case '+':
a_response.result = a_request.x + a_request.y;
break;
case '-':
a_response.result = a_request.x - a_request.y;
break;
case '*':
a_response.result = a_request.x * a_request.y;
break;
case '/':
a_response.result = (a_request.y != 0) ? (a_request.x / a_request.y): 0;
break;
}
"%d %c %d = %d", a_request.x, a_request.op, a_request.y, a_response.result
);
);
try {
clientSocket.send (a_response.code ());
}
catch (Exception& ex) {
ex.trace ();
}
}
El siguiente ejemplo muestra un cliente correspondiente al servidor anterior, que lanza un numero determinado de peticiones por segundo.
#include <iostream>
#include <string.h>
#include <anna.h>
#include <anna/comm/h>
#include <anna.timex.Engine.h>
#include <anna.timex.Clock.h>
#include <test.Response.h>
#include <test.Request.h>
class Sender : public timex::Clock {
public:
Sender () : Clock ("Sender", 250), a_messageBySecond (0), a_nquarter (0) {;}
void setMessageBySecond (const int messageBySecond) { a_messageBySecond = messageBySecond; }
private:
int a_messageBySecond;
int a_nquarter;
void tick () noexcept(false);
};
class MyCommunicator : public Communicator {
public:
MyCommunicator () : Communicator () {;}
private:
void eventReceiveMessage (ClientSocket &, const DataBlock&)
noexcept(false);
};
public:
HeavyClient ();
Server* getServer () const { return a_server; }
private:
MyCommunicator a_communicator;
timex::Engine a_timeController;
Sender a_sender;
Server* a_server;
void initialize () noexcept(false);
void run () noexcept(false);
};
using namespace std;
int main (int argc, const char** argv)
{
HeavyClient app;
srand (time (NULL));
try {
commandLine.initialize (argv, argc);
commandLine.verify ();
app.start ();
}
catch (Exception& ex) {
cout << ex.asString () << endl;
}
return 0;
}
HeavyClient::HeavyClient () :
Application ("arithmeticClient", "Cliente de operaciones aritmeticas", "1.0"),
a_communicator (),
a_timeController ((Millisecond)10000, (Millisecond)250)
{
}
void HeavyClient::initialize ()
noexcept(false)
{
Network& network = Network::instantiate ();
Host* host = network.find ("host000");
host->assign (network.find (Device::asAddress (cl.getValue ("a"))));
a_server = host->createServer ("rawServer", cl.getIntegerValue ("p"), true);
a_sender.setMessageBySecond (cl.getIntegerValue ("n"));
}
void HeavyClient::run ()
noexcept(false)
{
a_timeController.activate (a_sender);
a_communicator.accept ();
}
void MyCommunicator::eventReceiveMessage (ClientSocket&, const DataBlock& data)
noexcept(false)
{
a_response.decode (data);
"%d %c %d = %d", a_response.x, a_response.op, a_response.y, a_response.result
);
}
void Sender::tick ()
noexcept(false)
{
Communicator* communicator = anna::app::functions::component <Communicator> (
ANNA_FILE_LOCATION);
int maxn = a_messageBySecond / 4;
if (++ a_nquarter == 4) {
maxn += a_messageBySecond % 4;
a_nquarter = 0;
}
if (maxn == 0)
return;
maxn = rand () % maxn;
for (int n = 0; n < maxn; n ++) {
a_request.
x = rand () % 1000;
a_request.
y = rand () % 1000;
try {
server->send (a_request.
code ());
}
catch (RuntimeException& ex) {
ex.trace ();
break;
}
}
}
El ejecutable debera enlazarse con las librerias:
- libanna.core.a
- libanna.xml.a
- libanna.app.a
- libanna.comm.a
El Packet Header es anna/comm/h