Apache Mina Tutorial: Esempio Client Server di base
1.753 visite
Apache Mina Tutorial: Esempio Client/Server
Introduzione
Mina sta per ‘Multipurpose Infrastructure for Network Applications’ ed è un Java Framework utile per creare Applicazioni Network altamente scalabili e potenti, con semplicità. In questo articolo cercheremo di scrivere un Apache Mina Tutorial dimostrando come è semplice creare un Server che riceve messaggi da un Client.
Le librerie necessarie sono le seguenti:
- Apache Mina 2.0.x jars
- slf4j-api.jar
- slf4k-jdk14.jar
Il primo Jar è la libreria di Apache Mina che è attualmente arrivata alla versione 2.0.7. Le altre due librerie serviranno per scrivere i log della nostra applicazione.
Server
Creiamo un server composto da due Classi: MyMinaServer e MyMinaServerHandler.
Il MyMinaServer instanzia il IoAcceptor, indica l’ Handler nella Classe MyMinaServerHandler e il tipo di ProtocolCodecFilter da usare, per esempio in caso di scambio messaggi di testo useremo il TextLineCodecFactory.
Se possono creare ProtocolCodecFilter di propria mano a seconda delle proprie esigenze per esempio in caso il protocollo di scambio preveda XML si creerà un filtro che legge direttamente XML e restituisce le informazioni atomiche direttamente all’ Handler.
In altre parole il “ProtocolCodecFilter” è usato per convertire in ricezione un ByteBuffer in un messaggio POJO.
Di seguito il codice della classe MyMinaServer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
package com.geeknews.esempioserver; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MyMinaServer { private static final int PORT = 1234; public static void main(String[] args) throws IOException { //Instanziamo il NioSocketAcceptor IoAcceptor acceptor = new NioSocketAcceptor(); //Inseriamo nel Filtro il logger acceptor.getFilterChain().addLast("logger", new LoggingFilter()); //Aggiungiamo il TextLineCodecFilter che server per codificare e decodificare durante lo scambio di dati testuali acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); //Indichiamo l'handler del server acceptor.setHandler(new MyMinaServerHandler()); acceptor.getSessionConfig().setReadBufferSize(2048); //Indichiamo che la connessione verrà chiusa in caso di inutilizzo del canale socket sia lato client che lato server acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); //Il server sarà in ascolto alla porta stabilita acceptor.bind(new InetSocketAddress(PORT)); } } |
Il MyMinaServerHandler sarà una classe che estenderà la Classe di Mina IoHandlerAcceptor. In Questo modo erediterà alcuni metodi in @Override che sono i seguenti:
- sessionOpened
- messageReceived
- sessionIdle
- exceptionCaught
Ci sono altri metodi di cui potremmo fare l’@Override ma i 4 indicati sono quelli che serviranno al nostro esempio.
Il metodo SessionOpened verrà chiamato alla creazione del Socket con il Client.
Il metodo MessageReceived verrà chiamato quando viene ricevuto un messaggio.
sessionIdle sarà chiamato quando il canale di comunicazione Socket entra in uno stato Idle di inutilizzo.
exceptionCaught infine entrerà in gioco in caso di una eccezione Client o Server.
Quindi la classe MyMinaServerHandler sarà:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.geeknews.esempioserver; import org.apache.mina.core.session.IdleStatus; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyMinaServerHandler extends IoHandlerAdapter { private final Logger logger = (Logger) LoggerFactory.getLogger(getClass()); @Override public void sessionOpened(IoSession session) { // set dell' idle time a 10 secondi session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); session.setAttribute("Values: "); } @Override public void messageReceived(IoSession session, Object message) { logger.info("Messaggio ricevuto dal client.."); logger.info("Il messaggio è: " + message.toString()); } @Override public void sessionIdle(IoSession session, IdleStatus status) { logger.info("Disconnessione client in Idle."); // Disconnessione di un Client Idle session.close(); } @Override public void exceptionCaught(IoSession session, Throwable cause) { // close the connection on exceptional situation session.close(); } } |
Client
Il Client sarà altresì composto da due classi: MyMinaClient e MyMinaClientHandler.
La classe MyMinaClient instanzia un IoConnector e come il server indica il TextLineCodecFactory nel ProtocolCodecFilter, il logger e la classe Handler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.geeknews.esempioserver; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.service.IoConnector; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; public class MyMinaClient { private static final int PORT = 1234; public static void main(String[] args) throws IOException, InterruptedException { IoConnector connector = new NioSocketConnector(); connector.getSessionConfig().setReadBufferSize(2048); //Logger connector.getFilterChain().addLast("logger", new LoggingFilter()); //ProtocolFilter TextLineCodecFilter connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); //Set della classe Handler MyMinaClientHandler con il testo in input connector.setHandler(new MinaClientHandler("Ciao Server !")); ConnectFuture future = connector.connect(new InetSocketAddress("127.0.0.1", PORT)); future.awaitUninterruptibly(); if (!future.isConnected()) { return; } IoSession session = future.getSession(); session.getConfig().setUseReadOperation(true); session.getCloseFuture().awaitUninterruptibly(); System.out.println("After Writing"); connector.dispose(); } } |
Infine anche la classe MyMinaClientHandler IoHandlerAdapter e eredita 4 metodi che hanno lo stesso comportamento descritto nel MyMinaServerHandler. Di seguito la classe:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
package com.geeknews.esempioserver; import org.apache.mina.core.service.IoHandlerAdapter; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyMinaClientHandler extends IoHandlerAdapter { private final Logger logger = (Logger) LoggerFactory.getLogger(getClass()); private final String values; private boolean finished; public MinaClientHandler(String values) { this.values = values; } public boolean isFinished() { return finished; } @Override public void sessionOpened(IoSession session) { session.write(values); } @Override public void messageReceived(IoSession session, Object message) { logger.info("Messaggio receivuto dal server"); logger.info("Il Messaggio è: " + message.toString()); } @Override public void exceptionCaught(IoSession session, Throwable cause) { session.close(); } } |
Eseguendo i main delle rispettive classi e attivando il server e poi il client avremo il seguente output:
MyMinaServer output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Dec 8, 2010 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: CREATED Dec 8, 2010 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: OPENED Dec 8, 2010 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: RECEIVED: HeapBuffer[pos=0 lim=5 cap=2048: 54 65 73 74 0A] Message received in the server.. Message is: Hello Server.. Dec 8, 2010 8:32:00 PM org.apache.mina.filter.logging.LoggingFilter log INFO: IDLE Dec 8, 2010 8:32:00 PM com.sample.timeserver.TimeServerHandler sessionIdle INFO: Disconnecting the idle. Dec 8, 2010 8:32:00 PM org.apache.mina.filter.logging.LoggingFilter log INFO: CLOSED |
MyMinaClient output:
1 2 3 4 5 6 7 8 |
Lug 10, 2013 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: CREATED Lug 10, 2013 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: OPENED Lug 10, 2013 8:31:49 PM org.apache.mina.filter.logging.LoggingFilter log INFO: SENT: HeapBuffer[pos=0 lim=0 cap=0: empty] Lug 10, 2013 8:32:00 PM org.apache.mina.filter.logging.LoggingFilter log INFO: CLOSED |