- ベストアンサー
ソケット通信の受信でInputStreamの終了が認識できない
- ソケット通信の受信でInputStreamの終了が認識できない問題についての質問です。
- チャットクライアントのソースを流用し、バイト読み出しに変更した際に、入力ストリームの終了が正しく認識されず問題が発生しています。
- 具体的には、入力ストリームからの読み込みが終了しないため、forループから抜けることができない状況です。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
crossgateです。 レスが遅くなりました。 >1byte以上データがあると、for文の中の※5の箇所で取り込むのですが、 >入力ストリームが無くなっても、終了コード(-1)を返して来ないので、 >次の入力ストリームを待ってしまいfor文から抜けません。 なるほど。 何でバイト読み込みを自分で実装しようとしているかは良くわかりませんが。。。 単にブロックされたくないだけなら、 c = in.read(); if (c == -1) { break; } ではなくて、 if (in.available() == 0) { break; } c = in.read(); ならどうでしょう?
その他の回答 (2)
- crossgate
- ベストアンサー率65% (78/119)
>"-1"のチェックが使えない理由は何処に有るのか分かれば教えてください。それとも、そもそも >“public int read(byte b[], int off, int len) throws IOException{…}”を使う事が間違っていたのでしょうか? 理由は良く分かりません。 想像ですが、InputStream(もしくはそのサブクラス)のサブクラスをSocket用に作っていて、read()もそこでオーバーライドしているのかと。 つまり、元のソースはInputStream.read()を呼んでいる訳ではなくて、別のXXXXX.read()を呼んでいるんだとすると、read()が「-1」を返すための判定方法も違うだろうし、今回の話しは説明できると思います。 kn0100005さんは java\io\InputStream.java から取って来たんですよね? java\net 辺りにそんな感じのものが無いかチェックしてみてください。
お礼
>crossgateさん ありがとうごさいます。 探してみたところ“java\net\SocketInputStream.java”の中に、下記のメソッドが存在しました。 public int read(byte b[]) throws IOException { return read(b, 0, b.length); } public int read(byte b[], int off, int length) throws IOException { int n; // EOF already encountered if (eof) { return -1; } ・ ・ 略 ・ } ご指摘通り、実装するソースを間違えていた様です。 どうもありがとうございました。
- crossgate
- ベストアンサー率65% (78/119)
※4のread()は入力ストリームの先頭のバイトデータしか読み込んでいないからでは? 1byte以上データがあるとfor文の中にある「if (c == -1) { break; }」でブレークして「i」をreturnするだけのように見えますが。
補足
質問が間違っていたので訂正します。 =============================================================== ※4の下のfor文の中の下記の一行ですが、 c = in.read(); // ※5(←コメント追記) 元々は“c = read(); ”で、実装の際に“c = in.read(); ”と修正した物です。 (3)の文中の"※4"は、"※5"になります。 =============================================================== >crossgateさん 回答ありがとうございます。 1byte以上データがあると、for文の中の※5の箇所で取り込むのですが、 入力ストリームが無くなっても、終了コード(-1)を返して来ないので、 次の入力ストリームを待ってしまいfor文から抜けません。 宜しくお願いします。
お礼
>crossgateさん ありがとうごさいます。こちらの意図通り動いてくれました。 >何でバイト読み込みを自分で実装しようとしているかは良くわかりませんが。。。 実は、このクライアント側のソケット通信プログラムをandroidに組み込んでいるのですが、その際に、 別のメニュー画面から起動するアクティビティとして実装しています。 このソケット通信画面を抜けてメニュー画面に戻る際に、スレッド起動された受信部はストリーム待ち なので、そのスレッドが残ったままになってしまい、再度メニューから通信アクティビティを起動すると、 受信スレッドが重なって起動されてしまいました。 そこで100ms程度のタイムアウトで入力待ちを抜けて、スレッドの終了確認をする様に変更したのですが、 元のストリーム入力処理"in.read(w)"だと、データ受信中にタイムアウトとぶつかると、受信データの 配列への展開漏れが起きる恐れが有ったので、バイト単位の読込みに変更しようとして、この問題に ぶつかりました。 ですが、"in.available()"を使うことで、タイムアウト処理が不必要になったので、元の形に戻して シンプルなプログラムにする事が出来ました。 "-1"のチェックが使えない理由は何処に有るのか分かれば教えてください。それとも、そもそも “public int read(byte b[], int off, int len) throws IOException{…}”を使う事が間違っていたのでしょうか?