viernes, 25 de septiembre de 2009

Usar Apache Mina para comunicar Java y Python

He estado haciendo unas pruebas con Apache Mina, un framework para el desarrollo de aplicaciones en red en Java, necesitaba desarrollar un pequeño programa que funcione como servidor para obtener de el direcciones de red a las cuales se tienen que conectar diferentes maquinas, entonces, usando Apache Mina existe un Filtro que se encarga de decodificar y codificar los mensajes recibidos en formato de texto. Dicho filtro se puede obtener de TextLineCodecFactory, se tiene que indicar el Charset que se usa, en Linux se usa utf-8, por lo cual lo indicamos al crear el TextLineCodecFactory. Empece mis pruebas, el cliente para este servidor sera en otra plataforma diferente a Java. Decidi probar con Python y tenia un problema, el servidor recibia los mensajes pero no los pasaba al metodo messageReceived en donde los procesaria, simplemente invitiendo la cadena que me enviaran, como dije, este es solo un ejemplo. El asunto es que para que funcione el TextLineCodecFactory las cadenas que se envien deben terminar en salto de linea \n para que se tome que llego un mensaje nuevo, una vez agregado esto a los mensajes, todo funciono correctamente.

*** Este es el codigo del servidor modificado del ejemplo de Apache Mina: ***


import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoHandlerAdapter;
import org.apache.mina.common.IoSession;

/**
* {@link IoHandler} implementation of reverser server protocol.
*
* @author The Apache Directory Project (mina-dev@directory.apache.org)
* @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007) $,
*/
public class ReverseProtocolHandler extends IoHandlerAdapter {
@Override
public void exceptionCaught(IoSession session, Throwable cause) {
cause.printStackTrace();
// Close connection when unexpected exception is caught.
session.close();
}

@Override
public void messageReceived(IoSession session, Object message) throws Exception {
System.out.println("Mensaje recibido:" + message);
// Invertir la cadena
String str = message.toString();
StringBuffer buf = new StringBuffer(str.length());
for (int i = str.length() - 1; i >= 0; i--) {
buf.append(str.charAt(i));
}

String s = "Invertido: " + buf.toString();
//Enviar la cadena
session.write(s);
}

@Override
public void sessionCreated(IoSession session) throws Exception {
super.sessionCreated(session);
session.write("hola mundo");
}

@Override
public void sessionOpened(IoSession session) throws Exception {
super.sessionOpened(session);
session.write("hey mundo");
}
}


*** El codigo de la clase que pone en funcionamiento el servidor: ***



import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

/**
* (Entry point) Reverser server which reverses all text lines from
* clients.
*
* @author The Apache Directory Project (mina-dev@directory.apache.org)
* @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (Fri, 13 Jul 2007) $,
*/
public class Main {
private static final int PORT = 8080;

public static void main(String[] args) throws Exception {
IoAcceptor acceptor = new SocketAcceptor();

// Prepare the configuration
SocketAcceptorConfig cfg = new SocketAcceptorConfig();
//Aqui indicamos que el Charset es UTF-8
TextLineCodecFactory textLineCodecFactory = new TextLineCodecFactory(Charset.forName("UTF-8"));
cfg.setReuseAddress(true);
cfg.getFilterChain().addLast("logger", new LoggingFilter());
cfg.getFilterChain().addLast(
"codec",
new ProtocolCodecFilter(textLineCodecFactory));
// Bind
acceptor.bind(new InetSocketAddress(PORT),
new ReverseProtocolHandler(), cfg);


System.out.println("Listening on port " + PORT);
}
}


*** El codigo del cliente en python es este: ***


import socket
import time

if __name__ == '__main__':
# Se establece la conexion
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("localhost", 8080))

# Se recibe la respuesta y se escribe en pantalla
datos = s.recv(5000)
print datos

# Se espera respuesta, se escribe en pantalla y se cierra la
# conexion

# Se envia "hola"
mensaje = "hola\n"
s.send(unicode(mensaje, "utf-8" ))
datos = s.recv(5000)
#time.sleep(1)
print datos
mensaje = "probando\n"
#time.sleep(1)
s.send(unicode(mensaje, "utf-8" ))
datos = s.recv(5000)
print datos
# Se envia "adios"
s.send("adios\n")
#time.sleep(1)
s.close()

No hay comentarios:

Publicar un comentario