{{% toc %}}
MINA is:
MINA currently supports TCP and UDP based on Java NIO API, provides support for serial port communication, and transports based on Apache Portable Runtime.
It is known to perform as good as C/C++ servers. Please refer to the Performance Test Reports or the Testimonials.
Use the latest point-release of 2.0 (for Java 8 or above). 1.0 and 1.1 aren't maintained anymore.
JDK 7 or above is required to build MINA.
MINA core module depends on two libraries, SLF4J and backport-util-concurrent (for 1.0):
SLF4J (Simple Logging Facade for Java), a logging framework from the author of Log4J. SLF4J is very similar to Commons-Logging, but it doesn't cause any class loader issues at all. SLF4J provides bindings for Log4J, JDK 1.4 logging API, and NLog4J. Please put an appropriate SLF4J JAR file which corresponds to your favorite logging framework to the classpath as SLF4J documentation explains.
Spring framework and JZlib are also required to build integration-spring and filter-compression module.
The primary source to get help is the User Guide. You can also contact us via various channels to ask questions on MINA or to contribute to it.
You can contribute anything related with MINA; examples, useful codecs for existing protocols, tutorials, feature improvements, bug fixes, benchmarks, and whatever. Please contact us without hesitation.
Yes. You can create both client and server applications with MINA. Please take a look at IoConnector and IoAcceptor.
Yes. Please take a look at the Reversed and HTTP server examples. AsyncWeb is a HTTP server implementation based on MINA.
Yes. Please take a look at the SumUp example. There is no full ASN.1 support yet, but we will implement it someday and you can contribute to make it available sooner.
Yes. MINA doesn't close any connections unless you called IoSession.close()
or connection is closed by the remote peer.
We support SSL/TLS out-of-the-box. Please refer to SSLFilter
. It also provides a way to implement StartTLS. JDK 7 provides complete SASL support which works well with MINA.
It depends on your implementation. If you access the resource which is shared across multiple sessions, you have to make it thread-safe. If the resource is not shared at all and accessed by only one session (e.g. storing context information as a session attribute), then you don‘t need to make it thread-safe. It is because all events generated by MINA are transmitted to your handler in order (when using the Executor Filter), and the newer event is not processed if the event handler method for the older event for the same session hasn’t returned yet.
Virtually all kind of transport types. MINA API is designed to be transport-independent. You can implement any transport type support only if you can conform to MINA API. Support for Pre-1.4 I/O (aka BIO), reliable multicast, Java Communications API, and file I/O are planned.
Not yet. Java NIO doesn't support multicast yet. Multicast for NIO will be available in Java SE 7, Dolphin. We are seriously considering to implement multicasts using pre-1.4 Java API.
Sessions are capable of custom attributes that you can add or remove at any time. These custom attributes are not shared between sessions; it is designed to store session specific information.
Please refer to DemuxingIoHandler.
You have to do it in two steps : first close your sessions, then dispose the connector. Of course, if you dispose your Connector first, then all the sessions will be closed. Here is the code :
ConnectFuture cf = connector.connect(new InetSocketAddress("localhost", 8080)); // Get the close future for this session CloseFuture closeFuture = cf.getSession().getCloseFuture(); // Adding a listener to this close event closeFuture.addListener((IoFutureListener<?>) new IoFutureListener<IoFuture>() { @Override public void operationComplete(IoFuture future) { System.out.println("The session is now closed"); } }); // Do the close requesting that the pending messages are sent before // the session is closed closeFuture.getSession().close(false); // Now wait for the close to be completed closeFuture.awaitUninterruptibly(); // We can now dispose the connector connector.dispose();
Here is an example code:
public void sessionClosed( IoSession session ) throws Exception { // Wait for five seconds before reconnecting. Thread.sleep( 5000 ); // Reconnect. connector.connect( session.getRemoteAddress(), this ); }
Possibly it would be better to extract this code to a method like reconnect()
so that it can reusable in more than one place.
IoFilter
is usually considered reusable just like we think about Servlet filters. Please implement commonly used business logic such as authorization and logging as a filter. In case you implement just complex multi-layer protocols like Kerberos, you could consider using org.apache.mina.handler.chain
> package.
You can‘t use sessionIdle
event simply here. You’ll have to use java.util.concurrent.ScheduledExecutor
(or OpenSymphony Quartz as an alternative). Schedule a timeout task to be executed on timeout situation for each request message, and cancel it when you receive the corresponding response message.
Please refer to ‘Swapping implementations at deployment time’ section in the SLF4J Manual.
We recommend to switch the default buffer type to ‘heap’ by inserting the following code before you start a server:
ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(new SimpleByteBufferAllocator());
If you prefer direct buffers to heap buffers, JVM might have ran out of direct memory. Please try increasing maximum direct memory size using -XX:MaxDirectMemorySize option (e.g. -XX:MaxDirectMemorySize=128M)
Please make sure if you called ByteBuffer.flip()
to flip the buffer before writing the buffer out. It is a common mistake NIO beginners make.
Please make sure you called SSLFilter.setUseClientMode(true)
before you initiate a connection. Server developers will also have to disconnect users who doesn't initiate SSL handshake by setting IoSession.readerIdleTime
and closing the session in IoHandler.sessionIdle()
.
For example, I tried using SocketConnector to send “abc” and “def”, but it sent “abcdef”. Is it a MINA bug?
No, this is due to your OS trying to send packets more efficiently (see Nagle algorithm). You can enable/disable Nagle's algorithm by a call to SocketSessionConfig.setTcpNoDelay(), e.g.:
((SocketSessionConfig) connector.getSessionConfig()).setTcpNoDelay(false)
However, even if you do this you cannot expect one session.write(bytes) in MINA to correspond to one TCP packet on your network. You should probably implement your own MINA ProtocolDecoder to handle the assembly of incoming bytes into message objects. The TextLineCodec is a good start if the protocol you're implementing is based on text lines. For a more advanced example have a look at the SumUp example in the MINA distribution.
Please make sure if you are using the appropriate SLF4J version. You will get InvalidClassChangeError
if you are using outdated SLF4J release.
Network sockets are treated like files and your operating system has a limit to the number of file handles it can manage. Running out of file handles is usually due to a large number of clients connecting and disconnecting frequently. As specified by TCP, after being closed sockets remain in the TIME_WAIT state for some additional time. The reason is to ensure that delayed packets arrive on the correct socket. In Windows, the default TIME_WAIT timeout is 4 minutes, in Linux it is 60 seconds.
Update the configuration value by running (30 seconds used in the example)
echo 30 > /proc/sys/net/ipv4/tcp_fin_timeout
Restart the networking component, for example by running
/etc/init.d/networking restart
or
service network restart