web-dev-qa-db-ja.com

Java NIO:IOException:Broken pipeはどういう意味ですか?

一部のJava NIO接続では、SocketChannel.write(ByteBuffer)呼び出しがあると、IOException: "Broken pipe"がスローされます。

「破損したパイプ」の原因は何ですか?さらに重要なことは、その状態から回復することは可能ですか?回復できない場合は、これは不可逆的な問題が発生したことを示す良い兆候であり、このソケット接続を単純に閉じる必要があるようです。それは合理的な仮定ですか?最初の場所でソケット接続がまだ適切に接続されているときに(ある時点で失敗した有効な接続ではなく)このIOExceptionが発生することはありますか?

サイドノートでは、SocketChannel.isConnected()を試みる前に常にSocketChannel.write()を呼び出すのが賢明でしょうか。そうであれば、接続が「壊れて」おり、両方ともSocketChannel.isConnected()SocketChannel.isConnectionPending()は両方ともfalseですか?

ありがとう!

87
DivideByHero

「壊れたパイプ」の原因は何ですか、さらに重要なことは、その状態から回復することは可能ですか?

接続を閉じる原因となるものが原因です。 (接続を閉じたのはアプリケーションではありません。異なる例外が発生することになります。)

接続を回復することはできません。新しいものを開く必要があります。

回復できない場合は、これは不可逆的な問題が発生したことを示す良い兆候であり、このソケット接続を単純に閉じる必要があるようです。それは合理的な仮定ですか?

はい、そうです。その例外を受け取ったら、ソケットは再び機能しなくなります。それを閉じることが唯一の賢明なことです。

最初の場所でソケット接続がまだ適切に接続されているときに(ある時点で失敗した有効な接続ではなく)このIOExceptionが発生することはありますか?

いいえ(または、少なくとも、OSのネットワークスタック、JVM、および/またはアプリケーションの適切な動作を破壊することなく)。


SocketChannel.isConnected()を試みる前に常にSocketChannel.write()を呼び出すのが賢明ですか?.

一般に、(外部)リソースrを使用する呼び出しの前にr.isXYZ()を呼び出すことはお勧めできません。リソースの状態が変わる可能性はわずかですbetween 2つの呼び出し。アクションを実行し、失敗したアクションから生じるIOException(またはその他)をキャッチし、必要な修正アクションを実行することをお勧めします。

この特定のケースでは、isConnected()の呼び出しは無意味です。メソッドは、true過去にソケットが接続されていた場合を返すように定義されています。接続がまだ有効かどうかはわかりません。接続がまだ有効かどうかを判断する唯一の方法は、接続を使用することです。例えば読み取りまたは書き込みを行います。

96
Stephen C

パイプの破損は、単に接続が失敗したことを意味します。これは回復不能であると想定し、必要なクリーンアップアクション(接続を閉じるなど)を実行するのが妥当です。接続がまだ完了していないために、これが表示されるとは思わない。

非ブロックモードを使用している場合、SocketChannel.connectメソッドはfalseを返すため、isConnectionPendingおよびfinishConnectメソッドを使用して、接続が完了したことを確認する必要があります。私は通常、物事が機能するという期待に基づいてコーディングし、「isConnected」への頻繁な呼び出しに依存するのではなく、例外をキャッチして障害を検出します。

23
jsight

壊れたパイプは、もう一方の端ですでに閉じられている接続に書き込んだことを意味します。

isConnected()はこの状態を検出しません。書き込みのみが行います。

socketChannel.write()を試みる前に、常にSocketChannel.isConnected()を呼び出すのが賢明ですか

無意味です。 ソケット自体is接続されています。接続しました。 may接続されないのは接続自体であり、それを試すことによってのみ判断できます。

18
user207421

ソケットのもう一方の端が閉じられていると想定する必要があります。 IOExceptionのtry catchブロックでコードをラップします。

IsConnected()を使用してSocketChannelが接続されているかどうかを判別できますが、write()呼び出しが完了する前に変更される可能性があります。 catchブロックで呼び出して、実際にこれがIOExceptionを取得している理由であるかどうかを確認してください。

1