Keep-Alive の実装

HTTP プロキシサーバを作っていて、最もやっかいなのは Keep-Alive の実装かな。
ブラウザ側との Keep-Alive とウェブサイト側との Keep-Alive をしなければならない。
(Browser <-> Proxy, Proxy <-> WebSite)
ウェブサイト側の Socket を再利用しようとすると、既に切断されてたりしてその辺をどうするかだな。切断されてても、Socket.Connected は true だったりするしね・・・。
メッセージボディが長い可能性があるので、受信して MemoryStream にため込むってことはしたくない。
とりあえず考えたのは

  1. リクエストをブラウザから受け取る。
  2. リクエストボディを MemoryStream にすべて書き込む。
  3. リクエストとボディをウェブサイト側へ送信
  4. レスポンスをウェブサイトから受け取る
  5. レスポンスボディを MemoryStream にすべて書き込む。
  6. レスポンスとボディをブラウザへ送信

ってかんじだけど、これだとリクエストボディとかレスポンスボディが長かったら(たとえば 100Mbytes とか)、すべて受信し終わるまで待っておかなきゃいけないし、メモリを使いすぎるってところが問題。

現段階の実装は

  1. リクエストをブラウザから受け取る
  2. リクエストをウェブサイトへ送信
  3. リクエストボディがあればブラウザから受信(4096 bytes 程度。Content-Length などによる)・ウェブサイトへ送信繰り返す
  4. レスポンスをウェブサイトから受け取る
  5. レスポンスをブラウザへ送信
  6. レスポンスボディがあればウェブサイトから受信・ブラウザへ送信を繰り返す。

ってかんじ。いったんボディを読み込んで・・・とかしないで、4KBytes 程度を読み込んでは送信を繰り返してる。
でもなんか、ウェブサイトへリクエスト送信までは例外発生しなくても、レスポンス受信でリモートホストから切断とかなるので、いったいどういう事かと。Keep-Alive をちゃんと実装しないといかんのか。切断されてたらやり直したいところだけど、post とかでデータをブラウザから全部受信送信してたらやり直しのために post データを MemoryStream なんかに最初から保存してなければならないので、それもどうかと・・・。
やっぱ Keep-Alive の実装をしっかりして、時間過ぎたやつは使わないようにしないといけないか。