【问题标题】:Timeout on connect to socket using NIO SocketChannel [duplicate]使用 NIO SocketChannel 连接到套接字时超时 [重复]
【发布时间】:2013-04-28 11:04:12
【问题描述】:

我们有一个类通过套接字与另一个主机通信,它看起来像这样:

SocketChannel sc = SocketChannel.open(new InetSocketAddress(HOST, PORT));
sc.configureBlocking(true);

...
sc.write(...)
sc.read(...)

这个类很好用,除非 HOST 关闭,然后 SocketChannel.open 永远阻塞。我试图通过执行以下操作来使此超时:

SocketChannel  = SocketChannel.open();
sc.configureBlocking(false);
boolean result = socketChannel.connect(new InetSocketAddress(HOST, PORT));
if (!result) {
    long startTime = System.currentTimeMillis();
    while (!socketChannel.finishConnect()) {
        if (System.currentTimeMillis() - startTime< 1000) {
            // keep trying
            Thread.sleep(100);
        } else {
            // FAILED!
            enabled = false;
            return;
        }
    }
}
// SUCCESS!
socketChannel.configureBlocking(true);
enabled = true

好吧,由于某种原因,finishConnect() 会永远阻塞,而我本以为它根本不会阻塞。有什么想法吗?

【问题讨论】:

  • 阻塞是 NIO 的默认行为,所以你不需要设置它顺便说一句,即使大多数人认为它是关于非阻塞 IO。 AFAIK,您无法更改阻止模式。
  • @PeterLawrey 当然可以。这就是 'configureBlocking()' 的用途。
  • @EJP 感谢您的更正。我还没有看到它在一个区块中使用过,后来又换成了另一个。
  • @PeterLawrey 是的,你有。每个通道都以阻塞模式开始,因此每个使用选择器的程序都会显示更改为非阻塞模式。我不明白你的问题。

标签: java nio


【解决方案1】:

你做错了。

  1. 创建一个未连接的SocketChannel 并在阻塞模式下进行定时连接。

或

  1. 在非阻塞模式下使用Selector。注册OP_CONNECT的频道并选择。当它变得可连接时,调用finishConnect(),,如果它返回true,则取消注册OP_CONNECT并继续I/O。如果返回 false,请继续选择。如果它抛出异常,放弃连接,它就失败了。使用选择超时。不是自旋循环。

【讨论】:

  • BTW 你能安全地改变阻塞模式吗?
  • 谢谢。有人能解释一下“阻塞模式下的定时连接是什么意思”你的意思是在另一个线程中进行阻塞连接并等待该线程完成吗?
  • 没有。阻塞模式下的定时连接是通过Socket.connect(endpoint, timeout) 方法完成的。
  • @EJP 以任何方式使“定时连接”与SocketChannel 一起工作而不是普通的旧Socket?
  • @om-nom-nom 是的,请致电channel.socket().connect(...).
猜你喜欢
  • 2012-02-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-29
  • 2011-05-11
  • 1970-01-01
  • 2013-05-23
相关资源
最近更新 更多