- Se agrega un ejemplo de Receiver.
finalizar el request o no.
- Hacer un try/catch en cada llamada al socket por si se desconecto, para que no
muera con un segmentation fault.
+- Terminal Response para que lleguen bien todos los comandos al cliente.
+- Ver si sirve Runnable::signal_error y usar si sirve.
/// Cuerpo del mensaje.
std::string body;
- protected: // TODO hacer privados con get() y set() ???
-
- public:
+ public: // TODO hacer privados con get() y set() ???
/// Version HTTP.
std::string version;
#include "plaqui/server/connection.h"
#include <socket++/sockinet.h>
+#include <sigc++/signal.h>
#include <string>
namespace PlaQui {
/// Conexión para recibir el estado de una planta.
class Receiver: public Connection {
+ // Constantes.
+
+ private:
+
+ /// Marca de comienzo de frame.
+ static const std::string FRAME_BEGIN;
+
+ /// Marca de fin de frame.
+ static const std::string FRAME_END;
+
+
+ // Tipos.
+
+ public:
+
+ /// Tipo de señal para indicar que se recibió un cuadro.
+ typedef SigC::Signal1<void, const std::string&> SignalFrameReceived;
+
+
+ // Atributos.
+
+ private:
+
+ /// Señal que indica que se recibió un cuadro.
+ SignalFrameReceived frame_received;
+
+
+ // Métodos.
+
private:
/**
* \param port Puerto por el cual recibir estado de la planta.
* \param host Host del cual recibir el estado de la planta.
*/
- Receiver(int port = 7528, std::string host = "localhost");
+ Receiver(const Connection::Port& port = 7528,
+ const std::string& host = "localhost");
+
+ /**
+ * Obtiene la señal que avisa cuando se recibió un cuadro.
+ */
+ SignalFrameReceived& signal_frame_received(void);
};
//
#include "plaqui/server/receiver.h"
+#include <sstream>
#ifdef DEBUG
# include <iostream>
#endif // DEBUG
namespace Server {
+const string Receiver::FRAME_BEGIN("<plantstatus");
+
+const string Receiver::FRAME_END("</plantstatus>");
+
Receiver::~Receiver(void) {
#ifdef DEBUG
cerr << __FILE__ << ": destructor." << endl;
#endif // DEBUG
}
-Receiver::Receiver(int port, string host): Connection(sockbuf::sock_dgram) {
+Receiver::Receiver(const Connection::Port& port, const string& host):
+ Connection(sockbuf::sock_dgram, host, port) {
#ifdef DEBUG
cerr << __FILE__ << ": port = " << port
<< " | host = " << host << endl;
#endif // DEBUG
- // FIXME - deberia ir en run().
- socket->bind(port);
+ //socket->bind(port);
+ socket->bind(host.c_str(), port);
}
+// XXX EL XML DEBE EMPEZAR Y FINALIZAR EN UNA LINEA SEPARADA.
void Receiver::real_run(void) {
#ifdef DEBUG
cerr << __FILE__ << ": real_run." << endl;
#endif // DEBUG
- // FIXME - debería tirar una excepción?
- if (!socket->is_open()) {
- cerr << "No se pudo conectar a " << socket->peerhost() <<
- ":" << socket->peerport() << "." << endl;
- } else {
- cerr << "Conectado a " << socket->peerhost() <<
- ":" << socket->peerport() << "." << endl;
+ char buf[BUFSIZ];
+ bool in_frame = false;
+ stringstream ss;
+ while (!stop && socket.getline(buf, BUFSIZ)) {
+ string sbuf = buf;
+ if (in_frame) {
+ string::size_type pos = sbuf.find(FRAME_END);
+ if (pos == string::npos) { // No encuentra el fin
+ ss << sbuf << endl;
+ } else { // Encuentra el fin.
+ // Agrego al mensaje actual hasta el final </plantstatus>.
+ ss << sbuf.substr(0, pos + FRAME_END.length());
+ frame_received(ss.str());
+ ss.str("");
+ in_frame = false;
+ }
+ } else { // No esta en un frame.
+ string::size_type pos = sbuf.find(FRAME_BEGIN);
+ if (pos != string::npos) { // Encuentra el inicio
+ ss << sbuf.substr(pos) << endl;
+ in_frame = true;
+ }
+ }
}
}
+Receiver::SignalFrameReceived& Receiver::signal_frame_received(void) {
+ return frame_received;
+}
+
} // namespace Server
} // namespace PlaQui
LDFLAGS=-lsocket++ `pkg-config --libs glibmm-2.0 gthread-2.0` \
`xml2-config --libs` #-L$(LIB_FILES)
-TARGETS=server_test client_test
+TARGETS=server_test client_test receiver_test
# Regla por defecto.
all: $(TARGETS)
# Tests
server_test: $(LIB_FILES)/server.a $(MODEL_DIR)/src/model.a server_test.o
-
-# Tests
client_test: $(LIB_FILES)/server.a client_test.o
+receiver_test: $(LIB_FILES)/server.a receiver_test.o
clean:
rm -f $(TARGETS) *.o
#include "plaqui/server/controlclient.h"
#include "plaqui/server/string.h"
-//#include <socket++/sockinet.h>
#include <iostream>
#include <sstream>
#include <exception>
// Obtengo host.
host = argv[1];
}
- unsigned port = 7522;
+ Connection::Port port = 7522;
if (argc > 2) {
// Obtengo puerto.
stringstream str(argv[2]);
--- /dev/null
+// vim: set noexpandtab tabstop=4 shiftwidth=4:
+//----------------------------------------------------------------------------
+// PlaQui
+//----------------------------------------------------------------------------
+// This file is part of PlaQui.
+//
+// PlaQui is free software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the Free Software
+// Foundation; either version 2 of the License, or (at your option) any later
+// version.
+//
+// PlaQui is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+// details.
+//
+// You should have received a copy of the GNU General Public License along
+// with PlaQui; if not, write to the Free Software Foundation, Inc., 59 Temple
+// Place, Suite 330, Boston, MA 02111-1307 USA
+//----------------------------------------------------------------------------
+// Creado: jue nov 13 00:53:38 ART 2003
+// Autores: Leandro Lucarella <llucare@fi.uba.ar>
+//----------------------------------------------------------------------------
+//
+// $Id$
+//
+
+#include "plaqui/server/receiver.h"
+#include <iostream>
+#include <sstream>
+#include <exception>
+
+using namespace std;
+using namespace PlaQui::Server;
+
+void on_frame_received(const string& frame) {
+ cout << " Frame recibido! :-D" << endl;
+ cout << frame << endl;
+}
+
+int main(int argc, char* argv[]) {
+
+ // Termina con mas informacion si hay una excepcion no manejada.
+ set_terminate (__gnu_cxx::__verbose_terminate_handler);
+
+ // Mensaje de bienvenida.
+ cout << "Receiver test. Modo de uso: " << endl;
+ cout << "\t" << argv[0] << " [port] [host]" << endl;
+
+ // Parámetros.
+ Connection::Port port = 7528;
+ if (argc > 1) {
+ // Obtengo puerto.
+ stringstream str(argv[1]);
+ str >> port;
+ }
+ string host = "localhost";
+ if (argc > 2) {
+ // Obtengo host.
+ host = argv[2];
+ }
+
+ // Inicializa threads.
+ Glib::thread_init();
+
+ try {
+ // Corre el cliente.
+ Receiver receptor(port, host);
+ receptor.signal_frame_received().connect(SigC::slot(on_frame_received));
+ receptor.run(false);
+ } catch (const sockerr& e) {
+ cerr << "Socket Error: " << e.operation() << " | serrno = "
+ << e.serrno() << " | errstr = " << e.errstr() << endl;
+ if (e.io()) {
+ cerr << "Es: non-blocking and interrupt io recoverable error."
+ << endl;
+ } else if (e.arg()) {
+ cerr << "Es: incorrect argument supplied. recoverable error."
+ << endl;
+ } else if (e.op()) {
+ cerr << "Es: operational error. recovery difficult." << endl;
+ } else if (e.conn()) {
+ cerr << "Es: connection error." << endl;
+ } else if (e.addr()) {
+ cerr << "Es: address error." << endl;
+ } else if (e.benign()) {
+ cerr << "Es: recoverable read/write error like EINTR etc." << endl;
+ }
+ } catch (const exception& e) {
+ cerr << "Error: " << e.what() << endl;
+ } catch (const char* e) {
+ cerr << "Error: " << e << endl;
+ } catch (...) {
+ cerr << "Error desconocido!" << endl;
+ }
+
+ return 0;
+}