Fredrik Israelsson
Fredrik Israelsson

Reputation: 557

How to achieve timeout handling in blocking DatagramChannel without using selectors

I get a feeling that I am missing something really obvious here.

The overall structure of my system makes me want to use a blocking DatagramChannel without Selectors, in order to keep things simple. I am trying to achieve timeout handling by setting a timeout on the socket, but this seems to have no effect.

This pseudoized code gives a hint of what I am trying to achieve.

DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(some address);
channel.socket().setSoTimeout(3000);
channel.send(outBuffer, peerAddress);

channel.receive(inBuffer);

On the other side, I have a UDP server that gives five quick responses, and then, for testing purposes, delays about five seconds before delivering the sixth response.

The delay does not trigger a SocketTimeoutException. Why is that? The timeout set on the socket does not seem to be taken into consideration when calling channel.receive.

Regards, Fredrik

Upvotes: 9

Views: 3136

Answers (2)

user1537366
user1537366

Reputation: 1187

This is what I did:

Create an Interrupter class

static private class Interrupter implements Runnable
{
    private final Thread th1;
    private volatile int wait=-1;
    private Interrupter(Thread ith1)
    {
        th1=ith1;
    }
    public void run()
    {
        while(true)
        {
            try{
                if( wait<0 ){ th1.join(); break; }
                else{ Thread.sleep(wait); th1.interrupt(); wait=-1; }
            } catch(Exception e){}
        }
    }
}

Setup the Interrupter

Interrupter ir1=new Interrupter(Thread.currentThread());
Thread th1=new Thread(ir1);
th1.start();
// We need this so that later the wait variable
// can be passed in successfully
while( th1.getState()!=Thread.State.WAITING );

Use the Interrupter

try{
    ir1.wait=waitTimeout;
    th1.interrupt();
    // Receive on the socket
    dc2.receive(bb2);
} catch(ClosedByInterruptException e){
    // (Timed out)
    Thread.interrupted();
    dc2.close();
    // Handle timeout here
    // ...
    // We need this so that later the wait variable
    // can be passed in successfully
    while( th1.getState()!=Thread.State.WAITING );
}
// Received packet
ir1.wait=-1;
th1.interrupt();
// We need this so that later the wait variable
// can be passed in successfully
while( th1.getState()!=Thread.State.WAITING );
Thread.interrupted();

Upvotes: 1

D-Dᴙum
D-Dᴙum

Reputation: 7890

Apparently the issue of not being able to timeout is not a bug with DatagramChannel, but that:

Not a bug. The read methods in SocketChannel (and DatagramChannel) do not support timeouts. If you need the timeout functionality then use the read methods of the associated Socket (or DatagramSocket) object.

Link.

Upvotes: 7

Related Questions