This tutorial is designed to help you in writing a client and server using the MINA framework. In this tutorial we will write a server that displays memory usage for clients. This has some real world applicability in that you can place similar logic into any program in order to monitor the amount of memory that your program is using.
This tutorial has been verified on MINA 2.0.0 M3.
Building the code
For now MINA 2.0 final isn't released, but you can download the latest built version (2.0.0-M3).
If you prefer to build the code from the trunk, and need assistance to do so, please consult the Developer Guide.
The figure above depicts the sample UDP server. The Server is listening on the port 18567. The Client connects to the Server and sends the memory usage data. The figure above depicts two clients connected to the Server.
The Application Execution Flow
- The Server listens for incoming requests on port 18567
- The Client connects to the Server. The Server adds a Tab on Session Created event
- The Clients sends memory usage data to Server
- The Server adds the data received from Client in the tab added in Step 2
Server Code analysis
We will begin by looking at the code found in the
org.apache.mina.example.udp package under
mina-examples. To keep life simple, we shall concentrate on MINA related constructs only.
To construct the server, we shall have to do the following:
- Create a Datagram Socket to listen for incoming Client requests (See MemoryMonitor.java)
- Create an IoHandler to handle the MINA framework generated events (See MemoryMonitorHandler.java)
Here is the first snippet that addresses Point# 1:
Here, we create a NioDatagramAcceptor to listen for incoming Client requests, and set the IoHandler.The variable 'PORT' is just an int. The next step is to add a logging filter to the filter chain that this
DatagramAcceptor will use. LoggingFilter is a very nice way to see MINA in Action. It generate log statements at various stages, providing an insight into how MINA works.
Next we get into some more specific code for the UDP traffic. We will set the acceptor to reuse the address
Of course the last thing that is required here is to call bind().
There are three major events of interest for our Server Implementation
- Session Created
- Message Received
- Session Closed
Lets look at each of them in detail
Session Created Event
In the session creation event, we just call addClient() function, which internally adds a Tab to the UI
Message Received Event
In the message received event, we just dump the data received in the message. Applications that need to send responses, can process message and write the responses onto session in this function.
Session Closed Event
In the Session Closed, event we just remove the Client tab from the UI
Client Code Analysis
In this section, I will try to explain the client code. One note to make is that I left out the debugging/logging for brevity's sake. So here goes....
To implement the Client we need to do following:
- Create Socket and Connect to Server
- Set the IoHandler
- Collect free memory
- Send the Data to the Server
We will begin by looking at the file MemMonClient.java, found in the org.apache.mina.example.udp.client java package. The first few lines of the code are simple and straightforward.
Here we create a
NioDatagramConnector, set the handler and connect to the server. One gotcha I ran into was that you must set the host in the InetSocketAddress object or else nothing seems to work. This example was mostly written and tested on a Windows XP machine, so things may be different elsewhere. Next we will wait for acknowledgment that the client has connected to the server. Once we know we are connected, we can start writing data to the server. Here is that code:
Here we add a listener to the
ConnectFuture object and when we receive a callback that the client has connected, we will start to write data. The writing of data to the server will be handled by a method called sendData. This method is shown below:
This method will write the amount of free memory to the server once a second for 30 seconds. Here you can see that we allocate a
IoBuffer large enough to hold a long variable and then place the amount of free memory in the buffer. This buffer is then flipped and written to the server.