The challenge was to create a SIP User Agent with support
for 50 Calls per second. The current implementation used UDP and java io api’s. The implementation worked seamlessly for
10CPS from SIPP once we reached above 10CPS there was packet loss in the UDP
Datagram socket. We change the code to support worker threads but still the
loss was there. This prompted us to look for using other methods like queuing
or JMS.
I came across a article published by Jakob Jenkov on IO V/s NIO
http://java.dzone.com/articles/java-nio-vs-io and the tutorial provided by
http://tutorials.jenkov.com/java-nio/index.html
Java IO V/s Java NIO
The main difference between Java IO and Java NIO is
IO
|
NIO
|
Stream oriented
|
Buffer oriented
|
Blocking IO
|
Non blocking IO
|
|
Selectors
|
The biggest difference is Java IO is stream based and NIO is
buffer oriented. Java io being stream oriented can read one byte at a time .
They are not cached. Hence we need to cache it in a buffer first. Java NIO's being buffer oriented the approach different.
Data is read into a buffer from which it can be processed later. You can move
forth and back in the buffer as you need to. This gives you a bit more
flexibility during processing. However, you also need to check if the buffer
contains all the data you need in order to fully process it and, you need to
make sure that when reading more data into the buffer, you do not overwrite
data in the buffer you have not yet processed.
Java io is blocking which means the thread that read () or write
() block until there is some data to read or write. When large chunk of
messages are pumped into a UDP socket by the time worker thread reads the stream
it is blocked which cause packet loss
Java IO UDP Datagram
Server
UDPServer.Java
private final int
MAX_PACKET_SIZE = 2048;
private final byte[]
MAX_PACKET_ARRAY = new byte[MAX_PACKET_SIZE];
public void run()
{
try
{
String value = new String();
rxSocket = new DatagramSocket(8080, InetAddress.getByName(localhost));
DatagramPacket incomingPacket = new DatagramPacket(MAX_PACKET_ARRAY, MAX_PACKET_ARRAY.length);
while (true)
{
rxSocket.receive(incomingPacket);
if(incomingPacket.getLength()>0){
value = new String(incomingPacket.getData(), 0,
incomingPacket.getLength());
logger.info("Message from client - "+value);
ProcessClientMessages pi=new
ProcessClientMessages(value,sippclientthread,serverThread,serverinfoThread,incomingPacket.getAddress().getHostAddress(),incomingPacket.getPort());
tpes.submit(pi);
}
}
}catch
(Exception ex) {
ex.printStackTrace();
logger.error("Callconnector
Exception:" ,ex);
}
}
The above program is to recieve the UDP packet using Java IO.
Java NIO UDP Server
UDPServer.Java
static int i=0;
public void run()
{
try
{
String value = new String();
DatagramChannel channel =
DatagramChannel.open( );
DatagramSocket socket =
channel.socket( );
SocketAddress address = new
InetSocketAddress("8080");
socket.bind(address);
ByteBuffer buffer =
ByteBuffer.allocateDirect(65507);
byte byteArray[]=new byte[4096];
while (true)
{
SocketAddress client = channel.receive(buffer);
buffer.flip();
ipport=GeneralManipulation.getHostPort(client);
String fromIp=ipport[0];
String fromport=ipport[1];
while (buffer.hasRemaining( ))
{
byteArray[i]=buffer.get();
i=i+1;
}
i=0;
buffer.clear( );
value=new String(byteArray);
logger.info("str from client - "+value);
ProcessClientMessages pi=new
ProcessClientMessages(value,sippclientthread,serverThread,serverinfoThread,fromIp,Integer.parseInt(fromport));
tpes.submit(pi);
}
}catch
(Exception ex) {
ex.printStackTrace();
logger.error("Callconnector
Exception:" ,ex);
}
}
The above is the code with java nio channel api that
recieves messages on port 8080 and puts it in to the buffer and gets value from
it and processes it. ByteBuffer : we allocate size to the bytebuffer and the
channel which gets value will be in the buffer., (channel.receive(buffer);) then
we iterate the buffer and get value from it.
Summary
NIO helps you to manage multiple channels using a single
thread. If you need to connect multiple connections simultaneously using a
single thread to manage all outbound connections implementing NIO server is
probably an advantage