2010-03-15 77 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

相關問題