17

I want to use a SocketChannel and to have a timeout for its read/write methods. I've tried to set a timeout for the Socket that owns my SocketChannel like this:

channel.socket().setSoTimeout(TIMEOUT);

but that doesn't work. Is there any other solution?

user345171
  • 171
  • 1
  • 1
  • 3
  • 3
    Unfortunately, SocketChannel doesn't support the setSoTimeout method directly. Using it will sadly be disregarded. – casey Mar 26 '11 at 18:29
  • 9
    SocketChannel implements the InterruptibleChannel interface, which means that you could create a separate thread before entering your read() call, have that other thread set a timer and, when the timer expires, it could interrupt the thread in which your SocketChannel read() call is blocking. If the read() call returns first, you could have it kill the timer thread. – Stevens Miller Feb 03 '12 at 01:41
  • 5
    @StevensMiller And the channel will be closed, and the read will throw `ClosedByInterruptException.` Not very useful. I was told this bizarre implementation is mandated by the behaviour of Linux. – user207421 Feb 08 '15 at 22:32

3 Answers3

13

According to this article, SocketChannel will not timeout for its read operation but you can get this effect from reading from the channel in another way.

SocketChannel socketChannel;
socketChannel.socket().setSocketTimeout(500);
InputStream inStream = socketChannel.socket().getInputStream();
ReadableByteChannel wrappedChannel = Channels.newChannel(inStream);

reading from the wrappedChannel will timeout according to the socketTimeOut you have set.

luke
  • 14,518
  • 4
  • 46
  • 57
  • 1
    This is not the correct way to do this, only a workaround. The proper way is to use the Selector.select(timeout) in a loop and check the soTimeout/connectTimeout with an if-check – wzona Oct 13 '16 at 10:55
  • `setSocketTimeout` is now `setSoTimeout`, but works the same way. – Pedro Estevão Mar 07 '18 at 16:47
3

If you are familiar with using Java Selector, you can emulate socket timeout yourself using selector. It is helpful to see sun.nio.ch.SocketAdaptor.

It should be careful to use Thread.interrupt(). SocketChannel is InterruptibleChannel. As you read the description of InterruptibleChannel, Thread.interrupt() causes to close SocketChannel. If you want to use SocketChannel after timeout, you cannot use the InterruptibleChannel feature.

Eugene Chung
  • 352
  • 2
  • 10
-1

You could also consider making your channel non-blockable and just using System.currentTimeMillis().

Bat0u89
  • 610
  • 2
  • 17
  • 25