【Java】InputStream.read()でブロックされていることに気がつかず、躓いてしまった

InputStreamからデータを受け取ろうとして、read()をwhile内で呼び続ける処理を書いたのですが、ここでいくつか躓いてしまったのでメモ。

躓き1 InputStream.read()のブロック

InputStream.read()は、一見してデータをすべて受け取っていてもソケットを閉じるまでブロック、つまりread()を呼んでいる行で一時停止してしまう。
ブロックを解除するには、OutputStream.flush()するか、flush()をしてくれるOutputStream.close()を呼ぶ。

躓き2 InputStream.read()の返り値-1

InputStream.read()は返り値としてバイト数か-1を返す、と日本語訳されたリファレンスに記載されていて、ストリームの終わりに達したら-1を返すことを期待したコードを組んでいた。
しかし、read()から-1が返されず、-1が返される前提を勘違いしていたため躓き1で書いたようにブロックされてしまった。

躓き3 InputStream.availble()はそのままでは使えない

InputStream.read()の返り値は、通常今回読み込んだバイト数となる。
whileループでこれを回すとき、読み込むデータの終わりがいつなのかを調べたいとInputStream.availble()を使用したものの、期待するものが返り値にならなかった。
これはリファレンスにある通り、 InputStream クラスの available メソッドは常に 0 を返し、サブクラスはこのメソッドをオーバーライドする必要がある。