【问题标题】:Any issues with replacing new Socket() with SocketChannel.open().socket()?用 SocketChannel.open().socket() 替换 new Socket() 有什么问题吗?
【发布时间】:2013-11-15 12:55:11
【问题描述】:

如果我只是替换会出现什么问题

socket = new Socket()

socket = SocketChannel.open().socket()?

背景:我有一些使用new Socket() 的遗留代码,我希望能够中断socket.connect() 调用。我不想重写代码来使用 NIO。我了解到Thread.interrupt() 不会中断socket.connect(),但另一个线程上的socket.close() 应该会中断连接。奇怪的是,这适用于 Java 7,但不适用于 Java 6。

我不知何故想到使用socket = SocketChannel().open().socket() 会神奇地让我使用Thread.interrupt() 来打断socket.connect()。它没有,但奇怪的是,它确实使 socket.close() 在 Java 6 中中断 socket.connect()

请注意,我并没有以任何方式直接使用附加的 SocketChannel --- 它在我创建 Socket 时出现,以后再也不会出现。

这有什么问题?

【问题讨论】:

    标签: java sockets nio socketchannel


    【解决方案1】:

    有几个。

    1. 通过 SocketChannel 获取的 Socket 似乎不支持读取超时。
    2. 套接字的 InputStream 和 OutputStream 不是独立的:它们具有共同的互锁。

    为什么要中断 connect() 调用?当然你想要的只是连接超时?

    【讨论】:

    • (2) 不是问题,因为这是一个请求/响应协议。我会调查(1)。我想为Happy Eyeballs 中断connect():一个线程正在尝试IPv6,第二个线程正在尝试IPv4,如果IPv6 被破坏以致connect() 将超时,我想尽快中断connect()随着 IPv4 连接的建立。
    • 在这种情况下,您最好以非阻塞模式连接通道并关闭第二个触发 OP_CONNECT 的通道。
    • 我想我同意,但我希望避免为 NIO 重新配置代码的工作。但也许我可以在成功连接后配置回阻塞,然后只使用套接字流?您(或某人)能否显示将替换 socket = SocketChannel.open().socket(); socket.connect(address, timeout); 的代码?
    • 我的测试表明socket.setSoTimeout() 在通过 SocketChannel 获取的 Socket 上工作得很好,导致预期的 java.net.SocketTimeoutException 在阻塞 socket.getInputStream().read() 时被抛出。
    • 奇怪。我看到一个 Sun 错误报告表明相反。它在本网站的某处被引用。
    【解决方案2】:

    抛出的异常类型的差异可能会破坏现有代码。

    例如,在 Socket.getInputStream().read() 阻塞时从不同的线程关闭 Socket 将导致替换后的 AsynchronousCloseException,而不是旧代码可能期望的 SocketException。 (AsynchronousCloseException 不是SocketException 的子类。)

    但是,如果来自另一个线程的关闭在 read() 之前进入,Socket.getInputStream().read() 仍然会抛出 SocketException

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      • 1970-01-01
      • 2011-09-25
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      相关资源
      最近更新 更多