Date: Fri, 29 Mar 2024 13:18:21 +0000 (UTC) Message-ID: <420561336.5259.1711718301092@cwiki-he-fi.apache.org> Subject: Exported From Confluence MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_Part_5258_840501064.1711718301092" ------=_Part_5258_840501064.1711718301092 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Location: file:///C:/exported.html
This tutorial will walk you through the process of building a MINA based= program. This tutorial will walk through building a time server.&nbs= p; The following prerequisites are required for this tutorial:
slf4j-api.jar
, slf=
4j-log4j12.jar
, and Log4J 1.2.xslf4j-api.jar
, slf=
4j-log4j13.jar
, and Log4J 1.3.xjava.util.logging
users: slf4j-api.=
jar
and slf4j-jdk14.jar
slf4j-log4j12.jar
and log4j-1.3.x.jar can not be used together, and will malfunction.
I have tested this program on both Windows=C2=A9 2000 professional and l= inux. If you have any problems getting this program to work, please d= o not hesitate to contact us= a> in order to talk to the MINA developers. Also, this tutorial has t= ried to remain independent of development environments (IDE, editors..etc).= This tutorial will work with any environment that you are comfortabl= e with. Compilation commands and steps to execute the program have be= en removed for brevity. If you need help learning how to either compi= le of execute java programs, please consult the Java tut= orial.
We will begin by creating a file called MinaTimeServer.java. = The initial code can be found below:
public class MinaTimeServer { public static void main(String[] args) { =09// code will go here next } }
This code should be straightforward to all. We are simply defining=
a main method that will be used to kick off the program. At this poi=
nt, we will begin to add the code that will make up our server. First=
off, we need an object that will be used to listen for incoming connection=
s. Since this program will be TCP/IP based, we will add a Socke=
tAcceptor
to our program.
import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.transport.socket.nio.SocketAcceptor; public class MinaTimeServer { public static void main(String[] args) { // The following two lines change the default buffer type to 'heap'= , // which yields better performance.c ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); IoAcceptor acceptor =3D new SocketAcceptor(); } }
With the SocketAcceptor
class in place, we can go ahead and=
define the handler class and bind the SocketAcceptor
to a por=
t. If you are interested in adding a thread model to the SocketAccept=
or
, please read the Configuring Thread Model tutorial.
We will now add in the SocketAcceptor
configuration. This wil=
l allow us to make socket-specific settings for the socket that will be use=
d to accept connections from clients.
import java.io.IOException; import java.nio.charset.Charset; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.filter.LoggingFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.SocketAcceptor; import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; public class MinaTimeServer { private static final int PORT =3D 9123; public static void main(String[] args) throws IOException { ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); IoAcceptor acceptor =3D new SocketAcceptor(); SocketAcceptorConfig cfg =3D new SocketAcceptorConfig(); cfg.getFilterChain().addLast( "logger", new LoggingFilter() ); cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new= TextLineCodecFactory( Charset.forName( "UTF-8" )))); } }
Here was have created a new instance of the SocketAcceptorConfig=
code> class that will be used to pass in to the acceptor once we are ready =
to start up the acceptor. First, we have set the reuse address flag. See mo=
re information about this in the JDK Documentation. Next we add a filter to the conf=
iguration. This filter will log all information such as newly created sessi=
ons, messages received, messages sent, session closed. The next filter is a=
ProtocolCodecFilter
. This filter will translate binary or pro=
tocol specific data into message object and vice versa.
This last addition will bind the acceptor to the port. This method will = signal the startup of the server process. Without this method call, the ser= ver will not service client connections.
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.charset.Charset; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.IoAcceptor; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.filter.LoggingFilter; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.filter.codec.textline.TextLineCodecFactory; import org.apache.mina.transport.socket.nio.SocketAcceptor; import org.apache.mina.transport.socket.nio.SocketAcceptorConfig; public class MinaTimeServer { private static final int PORT =3D 9123; public static void main(String[] args) throws IOException { ByteBuffer.setUseDirectBuffers(false); ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); IoAcceptor acceptor =3D new SocketAcceptor(); SocketAcceptorConfig cfg =3D new SocketAcceptorConfig(); cfg.getFilterChain().addLast( "logger", new LoggingFilter() ); cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new= TextLineCodecFactory( Charset.forName( "UTF-8" )))); acceptor.bind( new InetSocketAddress(PORT), new TimeServerHandler()= , cfg); System.out.println("MINA Time server started."); } }
What you see here is that we have defined a variable port of type intege=
r and made a call to SocketAcceptor.bind(SocketAddress,IoHandler). Th=
e first parameter is the SocketAddress
that describes the netw=
ork address that will be listening on, in this case port 9123, and the loca=
l address.
The second parameter passed to the bind method is a class that must impl=
ement the interface IoHandler
. For almost all programs t=
hat use MINA, this becomes the workhorse of the program, as it services all=
incoming requests from the clients. For this tutorial, we will exten=
d the class IoHandlerAdapter
. This is a class that follo=
ws the adapter design pattern which simplifies t=
he amount of code that needs to be written in order to satisfy the requirem=
ent of passing in a class that implements the IoHandler
interf=
ace.
The third parameter is the configuration object, cfg, which has been con=
figured with a logger filter and a codec filter. MINA is set up such =
that each message that is received will be passed through any and all filte=
rs in the filter chain defined for the IoAcceptor
. In th=
is case, we will pass all messages through a logging filter and then a code=
c filter. The logging filter will simply log the message using the SL=
4J library, and the codec filter will decode each message received and enco=
de each message sent using the supplied TextLineCodecFactory
c=
lass.
Below is the class TimeServerHandler:
import java.util.Date; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoSession; import org.apache.mina.common.TransportType; import org.apache.mina.transport.socket.nio.SocketSessionConfig; public class TimeServerHandler extends IoHandlerAdapter { =09public void exceptionCaught(IoSession session, Throwable t) throws Excep= tion { =09=09t.printStackTrace(); =09=09session.close(); =09} =09public void messageReceived(IoSession session, Object msg) throws Except= ion { =09=09String str =3D msg.toString(); =09=09if( str.trim().equalsIgnoreCase("quit") ) { =09=09=09session.close(); =09=09=09return; =09=09} =09=09Date date =3D new Date(); =09=09session.write( date.toString() ); =09=09System.out.println("Message written..."); =09} =09public void sessionCreated(IoSession session) throws Exception { =09=09System.out.println("Session created..."); =09=09if( session.getTransportType() =3D=3D TransportType.SOCKET ) =09=09=09((SocketSessionConfig) session.getConfig() ).setReceiveBufferSize(= 2048 ); session.setIdleTime( IdleStatus.BOTH_IDLE, 10 ); =09} }
Here we have the code for the handler portion of the tutorial program.&n=
bsp; We have overridden the methods exceptionCaught, messageReceived and se=
ssionCreated. As stated previously, this class extends the IoHa=
ndlerAdapter
, which is a class that follows the Adapter design patte=
rn.
The exceptionCaught method will simply print the stack trace of the erro= r and close the session. For most programs, this will be standard pra= ctice unless the handler can recover from the exception condition.
The messageReceived method will receive the data from the client and wri=
te back to the client the current time. If the message received from =
the client is the word "quit", then the session will be closed. This =
method will also print out the current time to the client. Depending =
on the protocol codec that you use, the object (second parameter) that gets=
passed in to this method will be different, as well as the object that you=
pass in to the session.write(Object) method. If you do not specify a=
protocol codec, you will most likely receive a ByteBuffer
obj=
ect, and be required to write out a ByteBuffer
object.
The sessionCreated method is typically where your session initialization= occurs. In this case, we print out that the method has been entered,= and then test if the transport type of the sesion is socket based (versus = UDP), and then set the receive buffer size. In the case above, the in= coming buffer size is set to 2048 bytes. The idle time is also set to= 10 seconds. If we were to override the sessionIdle method, the sessi= onIdle method would get called every 10 seconds.
At this point, we can go ahead and compile the program. Once you h= ave compiled the program you can run the program in order to test out what = happens. The easiest way to test the program is to start the program,= and then telnet in to the program:
Client Output |
Server Output |
---|---|
user@myhost:~> telnet 127.0.0.1 9123 |
MINA Time server started. |
DIRMINA-659 issue rised the necessity of = adding a special permission when running MINA framework in a restricted env= ironnement like applets or Java Webstart technology. This happens when shut= ting down the thread pools (ExecutorService).
In order to get it to work properly, you will need to set the following = permission :
permission java.lang.RuntimePermission "modifyThread";=20
Or you can also choose to sign your code.
Please visit our Docu= mentation page to find out more resources. You can also keep reading ot= her tutorials.