Тайм-аут для SocketChannel не работает

Я хочу использовать SocketChannel и иметь тайм-аут для его методов чтения/записи. Я попытался установить тайм-аут для сокета, которому принадлежит мой SocketChannel, следующим образом:

channel.socket().setSoTimeout(TIMEOUT);

но это не работает. Есть ли другое решение?


person user345171    schedule 19.05.2010    source источник
comment
К сожалению, SocketChannel не поддерживает метод setSoTimeout напрямую. К сожалению, его использование будет проигнорировано.   -  person casey    schedule 26.03.2011
comment
SocketChannel реализует интерфейс InterruptibleChannel, что означает, что вы можете создать отдельный поток перед входом в ваш вызов read(), установить таймер в этом другом потоке, и, когда таймер истечет, он может прервать поток, в котором ваш вызов SocketChannel read() блокирует. Если вызов read() возвращается первым, вы можете убить поток таймера.   -  person Stevens Miller    schedule 03.02.2012
comment
@StevensMiller И канал закроют, и чтение выкинет ClosedByInterruptException. Не очень полезно. Мне сказали, что эта причудливая реализация обусловлена ​​поведением Linux.   -  person user207421    schedule 09.02.2015


Ответы (3)


Согласно этому article, SocketChannel не истечет время ожидания для операции чтения, но вы можете получить этот эффект от чтения из канала другим способом.

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

чтение из wrapChannel истечет по тайм-ауту в соответствии с установленным вами socketTimeOut.

person luke    schedule 05.02.2012
comment
Это не правильный способ сделать это, только обходной путь. Правильный способ - использовать Selector.select(timeout) в цикле и проверять soTimeout/connectTimeout с помощью if-check - person wzona; 13.10.2016
comment
setSocketTimeout теперь setSoTimeout, но работает так же. - person Pedro Estevao; 07.03.2018

Если вы знакомы с использованием Java Selector, вы можете самостоятельно эмулировать время ожидания сокета с помощью selector. Полезно посмотреть sun.nio.ch.SocketAdaptor.

Следует быть осторожным при использовании Thread.interrupt(). SocketChannel — это InterruptibleChannel. Когда вы читаете описание InterruptibleChannel, Thread.interrupt() вызывает закрытие SocketChannel. Если вы хотите использовать SocketChannel после истечения времени ожидания, вы не можете использовать функцию InterruptibleChannel.

person Eugene Chung    schedule 22.08.2013

Вы также можете сделать свой канал неблокируемым и просто использовать System.currentTimeMillis().

person Bat0u89    schedule 14.10.2012