users@grizzly.java.net

What is the correct way to write a Async UDP server

From: SATHISH SANTHANAM <sathish.santhanam_at_oracle.com>
Date: Thu, 12 Aug 2010 11:49:40 -0700

Hello,

I am trying to get a UDP server working with grizzly. The server needs
to send the response asynchronously - meaning, the UDP message is read
in the filter's handleRead(). But, the response will be sent by a
different thread later.

When we send the response, we want to set the source address to the same
port where the UDP server is receiving requests (so that the client will
see the response coming from the same destination where it sent the
request).

My question is - When a thread is ready to send the response, what is
the correct way to send it? Should it call

transport.connect(remote, local)
connection.getStreamWriter()
writer.writeByteArray()

When I do the above, I see some issues - some incoming messages to the
server are getting lost. I am wondering whether this is due to the fact
that I am binding another socket to the same local port (as part of
transport.connect above), but, I am using that socket only for write
purpose, no read is done on it.
If I use the same connection object which is available in handleRead(),
then, things seem to work fine. But, I would like to avoid it if
possible, because, I don't want to keep a map of all the connections for
which response is pending.

If the above is not the correct way, can you suggest the correct way to
handle the above scenario? Thank you.

Sathish

My code is something like this:

transport = UDPTransportFactory.createTransport();
    transport.getFilterChain().add(new UDPFilter());
    transport.bind(host, port);
    transport.start();

class UDPFilter extends FilterAdapter {
public NextAction handleRead(final FilterChainContext ctx, final
NextAction nextAction) {
//read the message from the connection
InetSocketAddress address = (InetSocketAddress) ctx.getAddress();
Buffer messageBuffer = (Buffer) ctx.getMessage();
final byte[] data = new byte[messageBuffer.remaining()];
messageBuffer.get(data);
new Thread(new MyRunnable(data, address)).start();
return nextAction;
}

class MyRunnable implements Runnable {
public void run() {
 //prepare the response and send it to the client
//what is the correct way to do this? - Should I use the same transport,
same/new connection?
transport.connect(remote, local) //local address is same as the where we
bound the server to
connection.getStreamWriter()
writer.writeByteArray()
connection.close()
}

Thank you.

Sathish