- PR -

InputStream#read() での例外処理

投稿者投稿内容
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-11-12 14:08
InputStreamの実装がPlainSocketImplが返すSoketInputStreamであるならば、
あなたの提示したサンプルソースコードでおこなわれるのは、そのようなフロー
ではないはずですよ、ということでした。

1. ls コマンド送信
2. 結果を受け取るソケットから、ソケットの接続相手から切断される、タイムアウト
等の理由で使用不可能になるまで全部読む。その間複数行のレスポンスがあっても、
その関数内で纏められて1つのレスポンスとしてかえされる。1リクエスト対1レスポンス
の対応は取れない。
3. 1秒待つ
4. ls コマンド送信
5. 2の結果使い物にならなくなったソケットからまた読もうとするが、すでに使用不
可能なソケットので常にエラー。
6. 1秒待つ
7.以降4〜6を繰り返し

あなたの省略コードをシステムに使用した場合、こうなりそうですよ。
転載するときに省略してしまったwhileループの中身が重要だった、というこ
とです。ソケットストリームのリード中のbreak条件を省略するなんて、ヒド
イデスよ〜orz

ということで、失礼しました。

本題の方ですが、あなたの自作ソースコードのレイヤーで責任をおうべきこと
なので、あなたのプロジェクトのコーディング規約等と照らし合わせてお好き
なように、でしょうか。

勿論、あなたのアプリケーションにとって異常系と考える例外的な状態が発生
した場合に、適切な例外を生成してスローするのは、全く正当な行為だと思い
ますよ。"異常な事態"をハンドリングする側も整理して書けるので、悪いこと
はないと思います。


[ メッセージ編集済み 編集者: シュン 編集日時 2004-11-12 15:06 ]
ねま
会議室デビュー日: 2004/11/10
投稿数: 18
投稿日時: 2004-11-13 02:02
引用:

シュンさんの書き込み (2004-11-12 14:08) より:
InputStreamの実装がPlainSocketImplが返すSoketInputStreamであるならば、
あなたの提示したサンプルソースコードでおこなわれるのは、そのようなフロー
ではないはずですよ、ということでした。

あなたの省略コードをシステムに使用した場合、こうなりそうですよ。
転載するときに省略してしまったwhileループの中身が重要だった、というこ
とです。ソケットストリームのリード中のbreak条件を省略するなんて、ヒド
イデスよ〜orz


全く持ってその通りです。
皆様には、混乱を招いてただただ恐縮するばかりです。
ただ、それには私の勘違い(-1 になっても InputStream は使い続けられる)
があり、今回は大変勉強になりました。

引用:

本題の方ですが、あなたの自作ソースコードのレイヤーで責任をおうべきこと
なので、あなたのプロジェクトのコーディング規約等と照らし合わせてお好き
なように、でしょうか。

勿論、あなたのアプリケーションにとって異常系と考える例外的な状態が発生
した場合に、適切な例外を生成してスローするのは、全く正当な行為だと思い
ますよ。"異常な事態"をハンドリングする側も整理して書けるので、悪いこと
はないと思います。


アドバイスありがとうございます。
で、結局こうしました。
 # なんか、回りまわって出発点に落ち着いたって感じです。
--------------------------------------------------------
  public String readSample() throws FooIOException {
    StringBuffer sb = new StringBuffer();
    try {
      while( true ) {
        int ch = in.read();
        if (ch < 0) {
          if (sb.length() > 0) {
            break; // 保険のつもり-----@
          } else {
            throw new FooIOException("Read error! :: session closed");
          }
        }
        sb.append((char) ch);

        // プロンプトが出力されたらここで抜ける -----A
      }
    } catch(IOException e) {
      throw new FooIOException("Read error! :: time out", e);
    }
    return sb.toString();
  }
--------------------------------------------------------
FooIOException という自作の例外を readSample() の上位でハンドリング
するようにしました。
エラー処理の内容としては、こんな感じです。
 ・timeout ならリトライ(3回まで)。-1 ならリトライなし。
 ・disconnect()
 ・スレッド終了
 ・エラーダイアログ表示

FooIOException が発生した場合は、ネットワークの障害と考えられるので
自動で再接続するようにはしていません。


[ メッセージ編集済み 編集者: ねま 編集日時 2004-11-13 02:16 ]

[ メッセージ編集済み 編集者: ねま 編集日時 2004-11-13 02:19 ]

[ メッセージ編集済み 編集者: ねま 編集日時 2004-11-13 04:04 ]

スキルアップ/キャリアアップ(JOB@IT)