Home Java Creating a simple server with Apache MINA

Creating a simple server with Apache MINA

by admin

Creating a simple server with Apache MINA
Apache MINA – is an open source library for writing client-server applications in Java.The latest version 2.0.4 was released on June 14, 2011.
In this article I will describe the process of creating a simple server using this library.

What do we write?

In this article we will write a simple server which you can telnet to.Once connected, the server will greet the client with the command time will tell how many seconds have passed since it connected, and the q will say goodbye and close the connection.
So, let’s begin.

Connecting to a project

In addition to the mainlibrary mina-core library is also required to be included in the slf4j (Simple Logging Facade for Java) which is used by MINA as an interface to various logging systems such as Apache log4j. It is required to connect slf4j-api and one of the logging implementations. In our example, we won’t be using logging, so we can use slf4j-nop

Entry Point and Ioacceptor

In the main method of the application, we need to create and configure IoAcceptor – object that will accept incoming connections. We need the following methods of it ( IoAcceptor extends the interface IoService and some methods are declared in it):

  • DefaultIoFilterChainBuildergetFilterChain()

    – Returns the so called "filterchain";

  • void setHandler(IoHandlerhandler)

    – Sets the handler, the object that holds the main logic of the server;

  • void bind(SocketAddress localAddress)

    – Starts listening to the specified address.

For our example, this would be NioSocketAcceptor which is an implementation of IoAcceptor for TCP/IP.

"Filter chain" and protocol

Before reaching the handler, all events (accepting a connection, receiving data, etc.) go through what is called a "filter chain". Filters can perform any actions that could be in the handler, but are not very relevant there – logging, etc.
One filter worth considering separately is ProtocolCodecFilter The task of this filter is to convert data from some object into a sequence of bytes when transmitting it, and into a formatted object from a sequence of bytes when receiving it. One of the filter constructors looks like this :

ProtocolCodecFilter(ProtocolCodecFactory factory)

In this article I will not talk about creating my own "factory", my protocol, for our example we will use one of the simplest and already implemented in MINA protocols – TextLine ("factory" is TextLineCodecFactory ), which converts a sequence of bytes into a string ( String ) and vice versa. Besides, when sending a string, an end of line character will be appended to it, and when received, the string will be sent along the "filter chain" or to the handler only when the same end of line character is received. The encoding and the line-end character can be specified in the constructor :

TextLineCodecFactory(Charset charset, StringencodingDelimiter, String decodingDelimiter)

So in the handler we have to deal with already shaped objects, in our case strings ( String ).
At the object DefaultIoFilterChainBuilder has several methods for adding filters, but we only need one :

void addLast(String name, IoFilter filter)

This method adds a filter to the end of the chain.
So now we can write the method main :

public static void main(String[] args) throws IOException{IoAcceptor acceptor = new NioSocketAcceptor();acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new TextLineCodecFactory(Charset.defaultCharset(), System.lineSeparator(), System.lineSeparator())));acceptor.setHandler(new MyMinaServerHandler());acceptor.bind(new InetSocketAddress(12345));}

Handler, IoHandler and IoSession

The handler is an implementation of the interface IoHandler , which contains the following methods :

  • void sessionCreated(IoSessionsession)

    – Called when connection is accepted;

  • void sessionOpened(IoSessionsession)

    – is called after sessionCreated ;

  • void sessionClosed(IoSession session)

    – Called when connection is closed;

  • void sessionIdle(IoSession session, IdleStatus status)

    – Called on idle status (by timeout);

  • void messageReceived(IoSession session, Object message)

    – Called when data is received;

  • void messageSent(IoSession session, Object message)

    – Called when data is sent;

  • void exceptionCaught(IoSession session, Throwable cause)

    – Called if an exception occurs.

In our example, it is sufficient to implement only a couple of them – sessionOpened and messageReceived , so instead of implementing the interface directly, we can extend the class IoHandlerAdapter , which is an empty interface implementation, and override the methods we need.
Subject IoSession is a representation of a session (aka connection). We need some of its methods :

  • WriteFuture write(Object message)

    – sends data;

  • CloseFuture close(boolean immediately)

    – Closes the connection. If immediately is false, the connection will be closed only after all pending data has been sent.

Also IoSession allows us to store the data related to the connection and we will use this to save the connection time. To do this, we will use two methods :

  • Object setAttribute(Object key, Object value)
  • Object getAttribute(Object key)

So now we can write the :

public class MyMinaServerHandler extends IoHandlerAdapter{public void sessionOpened(IoSession session){session.setAttribute("time", System.currentTimeMillis());session.write("Hello!");}public void messageReceived(IoSession session, Object message){switch (((String) message).trim()){case "time":session.write(String.format("You connected %d seconds ago", (System.currentTimeMillis() - (Long) session.getAttribute("time")) / 1000));break;case "q":session.write("Bye!");session.close(false);break;}}}

That’s all

Start the freshly built server and write on the command line or in the terminal :

telnet localhost 12345

The server responds to our commands :

Trying 127.0.0.1...Connected to localhost.Escape character is '^]'.Hello!timeYou connected 11 seconds agoqBye!Connection closed by foreign host.

The full source code can be downloaded here
Thanks for reading!

You may also like