Requisitos
mina-core.2.0.4.jar
sfl4j-simple-1.6.2.jar
sfl4j-api-1.6.1.jar
Introducción
Apache mina es un framework que nos ayuda a realizar conexiones con redes, udp y tcp, tambien creo que puede hacer algo con el serial (aqui no se menciona) pero este tutorial es solo la introduccion a este framework.
Por que usar mina? por que te ayuda a desarrollar sockets rapidamente es extencible, ampliable y facil.
La imagen de arriba muestra la arquitectura de apache mina.
Programando un time server
Todo el codigo esta dentro del metodo main y utilizaremos un try-catch para controlar las excepciones, lo primero que se debe de hacer es un objecto del tipo
IoAcaptor
Primero definiremos el puerto.
Para este tutorial utilizaremos el puerto
9123 y definiremos una variable miembro
private static final int PORT = 9123;
acceptor este objecto es el que se usa para recibir las conexiones de entrada. Con la clase
NioSocketAcceptor se puede defiir un handler, el handler sera la clase que haga el trabajo del socket.
IoAcceptor acceptor = new NioSocketAcceptor();
Los siguiente es crear un filtro y agregarlo a la configuracion.
acceptor.getFilterChain().addLast( "logger", new LoggingFilter() );
acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));
Ahora definiremos el handler, el handler es el que atendera las peticiones del cliente. Este handler esta separado en otra clase que hereda de
IoHandlerAdapter
acceptor.setHandler( new TimeServerHandler() );
Definimos dos metodos mas el buffer y el tiempo de in idle.
acceptor.getSessionConfig().setReadBufferSize( 2048 );
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
Entonces asi tendremos la primer clase
Main
package testmina;
import java.net.BindException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.transport.socket.SocketAcceptor;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
/**
*
* @author skuarch
*/
public class Main {
public static Logger logger = null;
private static final int PORT = 9123;
//==========================================================================
public Main() {
PropertyConfigurator.configure("log.properties");
logger = Logger.getLogger(getClass());
}
//==========================================================================
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new Main();
try {
//IoAcceptor acceptor = new NioSocketAcceptor();
SocketAcceptor acceptor = new NioSocketAcceptor();
acceptor.setReuseAddress( true );
//acceptor.getFilterChain().addLast("logger", new LoggingFilter());
acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8"))));
acceptor.setHandler(new TimeServerHandler());
acceptor.getSessionConfig().setReadBufferSize(2048);
acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10);
acceptor.bind(new InetSocketAddress(PORT));
acceptor.setCloseOnDeactivation(true);
} catch (BindException be) {
logger.error("error", be);
} catch (Exception e) {
logger.error("error", e);
}
} // end main
} // end class
Se utilizo testmina como paquete y el nombre de la clase es Main.
La clase TimeServerHandler
En esta clase de heredo de
IoHandlerAdapter pero tambien se puede utilizar la interfaz
IoHandler se sobre escriben los metodos
exceptionCaught,
messageReceived y
sessionIdle
exceptionCaught
Este metodo es el encargado de las excepciones solo imprime el stack trace y cierra la conexion, esta es una buen practica.
messageReceived
Este es el metodo que recibe los datos del cliente y escribe la fecha actual, si el mensaje que se recibe es
quit se cerrara la conexion.
sessionIdle
Este metodo es llamado segun se configuro en
acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );. y solo imprime el numero de idles
La clase se veria de esta forma
import java.util.Date;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.IoSession;
public class TimeServerHandler extends IoHandlerAdapter
{
@Override
public void exceptionCaught( IoSession session, Throwable cause ) throws Exception
{
cause.printStackTrace();
}
@Override
public void messageReceived( IoSession session, Object message ) throws Exception
{
String str = message.toString();
if( str.trim().equalsIgnoreCase("quit") ) {
session.close();
return;
}
Date date = new Date();
session.write( date.toString() );
System.out.println("Message written...");
}
@Override
public void sessionIdle( IoSession session, IdleStatus status ) throws Exception
{
System.out.println( "IDLE " + session.getIdleCount( status ));
}
}
Por ultimo para probar puedes utilizar telnet y el puerto, de esta forma
telnet localhost 9123
y dar entrer
Referencias
apache mina
video tutorial de apache mina
documentacion de apache mina
ejemplos de apache mina
ejemplo cliente servidor