HTTP プロキシサーバを作っていて、最もやっかいなのは Keep-Alive の実装かな。
ブラウザ側との Keep-Alive とウェブサイト側との Keep-Alive をしなければならない。
(Browser <-> Proxy, Proxy <-> WebSite)
ウェブサイト側の Socket を再利用しようとすると、既に切断されてたりしてその辺をどうするかだな。切断されてても、Socket.Connected は true だったりするしね・・・。
メッセージボディが長い可能性があるので、受信して MemoryStream にため込むってことはしたくない。
とりあえず考えたのは
- リクエストをブラウザから受け取る。
- リクエストボディを MemoryStream にすべて書き込む。
- リクエストとボディをウェブサイト側へ送信
- レスポンスをウェブサイトから受け取る
- レスポンスボディを MemoryStream にすべて書き込む。
- レスポンスとボディをブラウザへ送信
ってかんじだけど、これだとリクエストボディとかレスポンスボディが長かったら(たとえば 100Mbytes とか)、すべて受信し終わるまで待っておかなきゃいけないし、メモリを使いすぎるってところが問題。
現段階の実装は
- リクエストをブラウザから受け取る
- リクエストをウェブサイトへ送信
- リクエストボディがあればブラウザから受信(4096 bytes 程度。Content-Length などによる)・ウェブサイトへ送信繰り返す
- レスポンスをウェブサイトから受け取る
- レスポンスをブラウザへ送信
- レスポンスボディがあればウェブサイトから受信・ブラウザへ送信を繰り返す。
ってかんじ。いったんボディを読み込んで・・・とかしないで、4KBytes 程度を読み込んでは送信を繰り返してる。
でもなんか、ウェブサイトへリクエスト送信までは例外発生しなくても、レスポンス受信でリモートホストから切断とかなるので、いったいどういう事かと。Keep-Alive をちゃんと実装しないといかんのか。切断されてたらやり直したいところだけど、post とかでデータをブラウザから全部受信送信してたらやり直しのために post データを MemoryStream なんかに最初から保存してなければならないので、それもどうかと・・・。
やっぱ Keep-Alive の実装をしっかりして、時間過ぎたやつは使わないようにしないといけないか。