【问题标题】:Atomic non-blocking writes to stream sockets对流套接字的原子非阻塞写入
【发布时间】:2014-10-02 14:07:23
【问题描述】:

如果我write(byte[]) to an OutputStream 在由Channel 支持的非阻塞Socket 上获得from Socket.getOutputStream(),并且write() 抛出IllegalBlockingModeException,是否保证所有字节数组都被写入或没有是吗?

我在上面链接的文档中找不到明确的答案。

【问题讨论】:

    标签: java sockets nio nonblocking


    【解决方案1】:

    查看Channels.newOutputStream():的Javadoc

    如果在底层通道处于非阻塞模式时调用,结果流的写入方法将抛出 IllegalBlockingModeException。

    在尝试任何写入之前检查模式。没有其他实现是有意义的。如果可以写作,为什么会有例外呢?

    【讨论】:

    • 好的,所以答案是非阻塞通道的OutputStream是不可写的,句号,输出缓冲区是否会被当前的写操作填满,所以any 写尝试抛出IllegalBlockingModeException。所以你可以将通道切换到阻塞模式并使用流,然后切换到非阻塞模式并使用非阻塞的nio操作,但不能同时进行。
    【解决方案2】:

    简答:不要假设或不需要任何特定行为来实现代码的正确功能。

    长答案:没有办法笼统地确定;如果抛出 IOException,它可能发生在操作的任何时间点,之后流的状态应假定为“未定义”。

    尽管有 IllegalBlockingException 的 javadoc 声明

    Unchecked exception thrown when a blocking-mode-specific operation
    is invoked upon a channel in the incorrect blocking mode
    

    虽然措辞暗示在任何工作实际发生之前对其进行检查(在实际执行之后检查非法操作是没有意义的),但问题是异常可能发生在一组相关的对象,因此无法知道在抛出异常之前这些对象的状态是否发生了变化。

    最明智的选择是不尝试该操作,或者如果无法避免,则不要对异常发生后的流/通道状态进行任何特别假设。

    我会假设实际上不会写入任何字节,因为该条件仅在实际写入数据之前进行检查才有意义 - 但是 - 这实际上是 SocketChannelImpl 中的一个实现细节。您可以挖掘 sun.nio.ch.SocketChannelImpl 的源代码(在 src.zip 中未提供)以实际检查实现;但这只会为该特定实现提供明确的证据。

    【讨论】:

    • 下定决心。 “不要假设”还是“我会假设”?您提到的类没有抛出异常。
    猜你喜欢
    • 1970-01-01
    • 2017-01-16
    • 1970-01-01
    • 2011-10-09
    • 2013-02-23
    • 1970-01-01
    • 2010-10-31
    • 2013-10-15
    • 1970-01-01
    相关资源
    最近更新 更多