2010-03-15 78 views
2

ReadableByteChannel.read()的规范将-1显示为结束流的结果值。此外,如果线程中断,则可能导致ClosedByInterruptException为什么在ReadableByteChannel.read()中发生IOException()

现在我认为这将是所有 - 而且这是大部分时间。然而,现在,然后我得到如下:

java.io.IOException: Eine vorhandene Verbindung wurde vom Remotehost geschlossen 
at sun.nio.ch.SocketDispatcher.read0(Native Method) 
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:25) 
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:233) 
at sun.nio.ch.IOUtil.read(IOUtil.java:206) 
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:236) 
at ... 

我不unterstand为什么我不在这种情况下获得-1。此外,这不是一个干净的例外,因为我无法捕捉任何可能的IOException

因此,这里是我的问题:

  1. 这是为什么例外首先抛出?
  2. 可以肯定的是,读取抛出的任何异常都是关于套接字被关闭的吗?
  3. 这一切与write()相同吗?

顺便说一句:如果我打电话SocketChannel.close()我还必须打电话SocketChannel.socket().close(),或者这是否暗示了较早?

谢谢,斯特芬

+1

谷歌翻译异常翻译:“现有的连接被远程主机强行关闭” – 2010-03-15 20:25:12

+0

@Steffen:我试图回答你的一些担忧。希望它会有所帮助。 – 2010-03-19 15:35:28

回答

2

很有趣,但今天有人已经发布了一个链接到Fallacies of Distributed Computing

就你而言,作为一个优秀的德语译成英语翻译者告诉我An existing connection was forcibly closed by remote host

当你处理I/O,特别是Socket I/O时,你必须做好任何IOException的处理准备。

其中一些,如ClosedByInterruptException您可以智能处理。其他人,你可以

  1. 添加throws声明你的方法,让来电者处理的IOExceptions
  2. 裹的IOExceptions成指定给您的子系统
  3. 裹的IOExceptions成RuntimeException的特定或不检查例外您的子系统
  4. 记录IOException并继续。

在任何情况下,一旦发生IOException,您可能无法与该通道进行多少通信。因此,您可能只需关闭连接并稍后重试。

顺便说一句,read只会返回-1给你,如果你成功达到了流的末尾。在你的情况下,我相信,这个连接在中途关闭。

编辑在回答OP评论

我可以防止通道是 中断?

不,这是您正在使用的特定频道的属性。如果它实现了InterruptibleChannel,那么它是可中断的,并且将在收到线程中断时关闭。 java.nio.channels.SocketChannel是可中断的

该文档为 ClosedByInterruptException状态: “由 线程接收经过检查的异常时另一个线程中断 它被阻塞于一个信道的I/O操作 而”仍然如何 可以阻止,如果它是 非阻塞IO?

如果你看看ReadableByteChannel.read规范,你会看到,该方法被声明为只能扔IOException。然后在JavaDoc中,它提示了什么样的特定IOException,以及这个接口的标准java.nio实现可能抛出什么条件。这是合作编程的例子之一。接口的声明者告诉实现者他们应该如何实现该方法,以及他们应该在什么条件下抛出什么异常。

例如,如果我在异国情调的通道中实现读取方法,我可能会选择完全忽略规范并且不会在声明中抛出任何异常。尽管我的课程的用户在遇到意外的行为时可能会付出沉重的代价,并且可能会转储我的实施,转而使用更强大的实施。

无论如何,我认为你对如何应对read方法中声明的不同异常感到困惑。首先,并不是读取方法规范中的每个异常都可能被抛出。在使用非阻塞I/O的情况下,最有可能不会抛出案例点ClodesByInterruptException。另一方面,一些实现者可能会在收到中断时选择关闭通道,并在尝试读取时抛出此异常,即使您处于非阻塞I/O中。但你真的不应该得到关注的这一决定,是因为:

  1. 你可能控制电流 线程是否被中断或不
  2. 这只是另一种 IOException的,默认情况下应 对待致命

是的,示例IOEception是 致命的,但我的问题是:他们 呢?

记住,你的框架应正常工作,或关机时摆好任何类型的异常被抛出。例如,您的代码或库代码在任何时候都可以引发未经检查(运行时)异常。只有对环境的测试和更深入的了解才能告诉您哪些例外是致命的,哪些可以安全处理。

因为框架是由人写的,所以他们也有bug,缺陷等。所以可能会出现抛出IOException的情况,但底层通道仍然可以。不幸的是,这些情况只能在真实的生产环境中发现血与胆。这是一个例子,其中由套接字抛出的IOException可以完全忽略:http://bugs.sun.com/view_bug.do?bug_id=4516760

因此,首先为所有IOExceptions编写通用处理程序,并将它们全部视为致命处理,然后将其放在您在生产中找到的特定条件中。

+0

+1得到比我更好的答案 – Dancrumb 2010-03-15 23:39:40

+0

我知道这些谬论,我尊重他们。我不明白的是: * SUCCESSFULLY *达到流结束和正在关闭的流“midstream”之间的区别是什么?请注意,我正在读入一个字节缓冲区,并且我没有试图去解密任何东西,因此物理上根本就没有在接收到TCP FIN时,在流中有更多的字节,就是这样呢? – 2010-03-17 12:28:44

+0

还有一点评论:你确定,在我得到任何'IOException'后,我什么都不能再做一个套接字了?这是安全的,我将简单地捕获IOException异常并处理它们,就像我现在处理ClosedByInterruptException一样:我正在关闭这个套接字,但我不明白以下两点:为什么我不能获得'-1'和为什么'ClosedByInterruptException'发生在所有?没有o f我的套接字被阻塞,这似乎是由'ClosedByInterruptException'的规范所建议的。 – 2010-03-17 12:33:57

0

每文档here

当另一个线程中断它 它是建立一通道阻塞在一个I/O 操作,同时由一个线程 接收经过检查的异常。在 异常抛出之前,通道将会关闭 ,并且先前被阻塞的 线程的中断 状态将被设置。

这表明拥有ReadableByteChannel的线程正在被应用程序中的另一个线程中断......是这种情况吗?

如果另一个线程关闭了频道,我希望你会看到一个AsynchronousCloseException

我看不出一个理由,为什么你不能赶上ClosedByInterruptException明确,并允许其他任何例外处理的堆栈更高:

try 
{ 
    rbc.read(dst); 
} 
catch (ClosedByInterruptException cbie) 
{ 
    /* handler */ 
} 

至于write(),不存在用于write()方法ReadableByteChannel,然而,WritableByteChannel,确实有一个write()方法,它可以抛出相同的例外。

+0

我可以捕获'ClosedByInterruptException',但我没有得到那个,只是一个'IOException'(参见上面的stacktrace)。同样在我的情况下,连接被远程关闭,线程不会中断。 (当然我在'WriteableByteChannel'中写'(')'我期待这是可以期待的 – 2010-03-15 20:28:17

相关问题