Home >Backend Development >PHP Tutorial >Apache Mina study notes (2) - Basics
In Chapter 1, we have a general understanding of MINA. In this chapter, we will make a detailed analysis of the client/server model in MINA. And some examples based on TCP and UDP will also be provided.
Application structure
Server structure
Client structure
Simple TCP server
Simple TCP client
Simple UDP server
Simple UDP client
Summary application structure
The structure of an application using the MINA framework is as follows:
From above As you can see in the figure, MINA acts as a middle layer to connect your application and the bottom layer of the network. It can handle TCP, UDP and even a serial communication protocol (RS-232C), so you can focus more on designing applications on MINA. Without needing to understand the complexity of underlying network communications.
Let’s take a look at the inside of MINA:
Generally speaking, MINA applications are divided into three layers.
I/O service - real I/O operation
I/O filter chain - filter/transmit data
I/O Handler - complete the logic of the program here
So, to create a MINA application, you only need to do:
Create I/O service - select an already provided service (Acceptor) or create your own service
Create a filter chain - select an already provided service Filter chain or create your own customized filter chain
Create I/OHandler - write business logic and process various messages. The above is the overall structure of MINA.
Let’s take a look at the structure of the server:
Simply put, there is an I/O Acceptor on the server side that listens for incoming connections or data packets. For a new connection to arrive, a new session will be created, and Subsequent requests coming from this connection will be processed in this session. All packets are accepted by the session and pass through the filtering chain indicated in the figure above. Filter chains are used to modify the contents of the package (such as converting to Objects, adding or removing some information). Finally these packets are processed by IOHandler. Another thing to note is that when a connection arrives, a session will be established, regardless of whether the connection is successful or not, the session will be established.
The following is the client model:
The client will have an IOConnector to connect to the server. And all processing is still completed by IOHandler.
Simple TCP server
Below, create a simple TCP server as a demonstration: First, you need to import some required packages into the IDE or configure your CLASSPATH. The specific method will not be detailed. Yes, the required packages are:
MINA 2.x Core
JDK 1.5 or greater
SLF4J 1.3.0 or greater
Log4J 1.2 users: slf4j-api.jar, slf4j-log4j12.jar, and Log4J 1.2.x
Log4J 1.3 users: slf4j-api.jar, slf4j-log4j13.jar, and Log4J 1.3.x
java.util.logging users: slf4j-api.jar and slf4j -jdk14.jar
IMPORTANT: Please make sure you are using the right slf4j-*.jar that matches to your logging framework.
After the preparations are completed, we start writing code
import java.net.InetSocketAddress; import org.apache.mina.core.service.IoAcceptor; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer { private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.bind( new InetSocketAddress(PORT) ); } }Next, we add the configuration of the filter chain in the above code.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; 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 MinaTimeServer { public static void main( String[] args ) { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); //这里会建立所有的日志信息 acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); //第二个过滤器用来传递数据 acceptor.bind( new InetSocketAddress(PORT) ); } }Next, we need to define the Handler used to process messages. This Handler class must implement the IoHandler interface. In MINA, this Handler is the key to program development. In this tutorial, we will inherit from IoHandlerAdapter.
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 )); } }Finally, the complete server code is as follows:
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.core.service.IoAcceptor; 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.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; public class MinaTimeServer { private static final int PORT = 9123; public static void main( String[] args ) throws IOException { IoAcceptor acceptor = new NioSocketAcceptor(); acceptor.getFilterChain().addLast( "logger", new LoggingFilter() ); acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.setHandler( new TimeServerHandler() ); //这里设置Handler acceptor.getSessionConfig().setReadBufferSize( 2048 ); //这是设置ssesion缓冲区 acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 ); acceptor.bind( new InetSocketAddress(PORT) ); } }Run the server, then open the terminal and enter the command: telnet 127.0.0.1 9123 You will see that when you enter something other than "quit" Any character, the server will return the current time to the terminal.
Simple TCP client
import java.net.InetSocketAddress; import org.apache.mina.core.RuntimeIoException; import org.apache.mina.core.future.ConnectFuture; import org.apache.mina.core.session.IoSession; import org.apache.mina.example.sumup.codec.SumUpProtocolCodecFactory; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory; import org.apache.mina.filter.logging.LoggingFilter; import org.apache.mina.transport.socket.nio.NioSocketConnector; /** * (<strong>Entry Point</strong>) Starts SumUp client. * * @author <a href="http://mina.apache.org">Apache MINA Project</a> */ public class Client { private static final String HOSTNAME = "localhost"; private static final int PORT = 8080; private static final long CONNECT_TIMEOUT = 30*1000L; // 30 seconds // Set this to false to use object serialization instead of custom codec. private static final boolean USE_CUSTOM_CODEC = true; public static void main(String[] args) throws Throwable { if (args.length == 0) { System.out.println("Please specify the list of any integers"); return; } // prepare values to sum up int[] values = new int[args.length]; for (int i = 0; i < args.length; i++) { values[i] = Integer.parseInt(args[i]); } NioSocketConnector connector = new NioSocketConnector(); // Configure the service. connector.setConnectTimeoutMillis(CONNECT_TIMEOUT); if (USE_CUSTOM_CODEC) {
connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new SumUpProtocolCodecFactory(false))); } else { connector.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new ObjectSerializationCodecFactory())); } connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.setHandler(new ClientSessionHandler(values)); IoSession session; for (;;) { try { ConnectFuture future = connector.connect(new InetSocketAddress( HOSTNAME, PORT)); future.awaitUninterruptibly(); session = future.getSession(); break; } catch (RuntimeIoException e) { System.err.println("Failed to connect."); e.printStackTrace(); Thread.sleep(5000); } } // wait until the summation is done session.getCloseFuture().awaitUninterruptibly(); connector.dispose(); } }I won’t write the UDP example. If necessary, go to the Apache official website to take a look.
http://mina.apache.org/mina-project/userguide/ch2-basics/sample-udp-client.html
The above is Apache Mina learning Notes (2) - Basic content, please pay attention to the PHP Chinese website (www.php.cn) for more related content!