【问题标题】:Timeout for SocketChannel doesn't workSocketChannel 超时不起作用
【发布时间】:2011-02-21 10:24:09
【问题描述】:

我想使用SocketChannel 并为其读/写方法设置超时。我试图为拥有我的SocketChannel 的 Socket 设置超时,如下所示:

channel.socket().setSoTimeout(TIMEOUT);

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

【问题讨论】:

  • 很遗憾,SocketChannel 不直接支持 setSoTimeout 方法。遗憾的是,使用它会被忽视。
  • SocketChannel 实现了 InterruptibleChannel 接口,这意味着您可以在进入 read() 调用之前创建一个单独的线程,让其他线程设置一个计时器,当计时器到期时,它可以中断线程您的 SocketChannel read() 调用被阻塞。如果 read() 调用首先返回,您可以让它终止计时器线程。
  • @StevensMiller 并且频道会被关闭,读取会抛出ClosedByInterruptException. 不是很有用。有人告诉我,这种奇怪的实现是 Linux 的行为所要求的。

标签: java socketchannel


【解决方案1】:

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

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

从 WrappedChannel 读取会根据你设置的 socketTimeOut 超时。

【讨论】:

  • 这不是正确的方法,只是一种解决方法。正确的方法是在循环中使用 Selector.select(timeout) 并使用 if-check 来检查 soTimeout/connectTimeout
  • setSocketTimeout 现在是 setSoTimeout,但工作方式相同。
【解决方案2】:

如果您熟悉使用 Java Selector,您可以使用 selector 自己模拟套接字超时。看看 sun.nio.ch.SocketAdaptor 会很有帮助。

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

【讨论】:

    【解决方案3】:

    您也可以考虑让您的频道不可阻塞,只使用 System.currentTimeMillis()。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-07
      • 2018-12-27
      • 2012-05-15
      • 1970-01-01
      • 2011-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多