2010-05-19 75 views
14

我想使用SocketChannel并有其读/写方法超时。我试图设置超时为拥有我SocketChannel这样的插座:超时的SocketChannel不起作用

channel.socket().setSoTimeout(TIMEOUT); 

,但不起作用。还有其他解决方案吗?

+3

不幸的是,SocketChannel不直接支持setSoTimeout方法。使用它将会被遗忘。 – casey 2011-03-26 18:29:55

+5

SocketChannel实现了InterruptibleChannel接口,这意味着您可以在进入read()调用之前创建一个单独的线程,让其他线程设置一个计时器,并且在计时器到期时,它可能会中断SocketChannel读取的线程()呼叫被阻止。如果read()调用首先返回,那么可以让它终止计时器线程。 – 2012-02-03 01:41:09

+4

@StevensMiller通道将被关闭,读取将抛出'ClosedByInterruptException.'不是很有用。我被告知这种奇怪的实现是由Linux的行为强制的。 – EJP 2015-02-08 22:32:57

回答

14

根据此article,SocketChannel将不会超时读取操作,但您可以通过另一种方式从通道中读取此效果。

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

从wrappedChannel中读取将根据您设置的socketTimeOut超时。

+0

很好的解决方案。 Java是...卡住 – 2015-09-11 06:45:36

+1

这不是正确的方法来做到这一点,只有一个解决方法。正确的方法是在一个循环中使用Selector.select(timeout),并用if if检查soTimeout/connectTimeout – wzona 2016-10-13 10:55:52

+0

'setSocketTimeout'现在是'setSoTimeout',但工作方式相同。 – 2018-03-07 16:47:15

-1

你也可以考虑让你的频道不可阻挡,并使用System.currentTimeMillis()。

2

如果您熟悉使用Java Selector,则可以使用选择器模拟套接字超时。看到sun.nio.ch.SocketAdaptor是有帮助的。

它应该小心使用Thread.interrupt()。 SocketChannel是InterruptibleChannel。在您阅读InterruptibleChannel的描述时,Thread.interrupt()会导致关闭 SocketChannel。 如果您想在超时后使用SocketChannel,则无法使用InterruptibleChannel功能。