NetworkStream.DataAvailable == false は、すぐに読めるバイトが無いことを意味する。HTTP レスポンスが完了したことを意味するわけではない。そこで止まるループは、パケット間の間隙でごく普通の SOCKS ダウンロードを切り詰めかねない。

SOCKS が TCP 接続を確立した後も、完了規則を与えるのは HTTP のフレーミングである:

  • Content-Length のボディは、宣言されたコンテンツバイトの後に終わる。
  • chunked レスポンスには終端チャンクと該当する trailer が必要である。
  • 接続で区切られたレスポンスは接続とともに終わる。
  • 一部のステータスと HEAD へのレスポンスにはボディが無い。

適用される規則を決めるにはステータスとヘッダーを読む。閉鎖だけを待つのは一般的な解決策ではない。完全な HTTP レスポンスでも接続が開いたままになることがあるからだ。1 つのバッファーの容量もレスポンスの長さとは無関係である。

選択したプロキシ転送を HTTP クライアントのフレーミング実装が支える場合はそれを使う。互換性のある現代の .NET ランタイムでは HttpClient のネイティブ SOCKS サポートを検討する。生の実装では、部分的なヘッダー読み取りとボディ読み取りの間で解析状態を保ち、正常な完了をキャンセル、タイムアウト、予期しない EOF と区別しなければならない。空でない読み取り要求では、0 バイトの読み取りはストリームの終了を意味する。これは今キューにバイトが無いこととは異なる。

プロキシはタイミングの間隙を目立たせることがあるが、空の受信キューをメッセージ終端の印に変えるわけではない。

関連記事