QA@IT

HttpWebRequest の KeepAlive の使い方

10132 PV

C#で HttpWebRequest を利用してリクエストを出します。
やりたいことは、同じサイトに対して、一回の接続で、2回リクエストを出したいです。

MSDNサイトからサンプルをいただき、理解できないところがあります。
http://msdn.microsoft.com/ja-jp/library/system.net.httpwebrequest.keepalive.aspx

1 HttpWebRequest myHttpWebRequest1 =
2        (HttpWebRequest)WebRequest.Create("http://www.contoso.com");
3
4      myHttpWebRequest1.KeepAlive=false;
5      // Assign the response object of HttpWebRequest to a HttpWebResponse variable.
6      HttpWebResponse myHttpWebResponse1 = 
7        (HttpWebResponse)myHttpWebRequest1.GetResponse();

4行目に、KeepAlive=true で、理論上は、通信チャンネルが持続して、
2回目以降のリクエストも同じ接続になりますが、
しかし、URLの設定は、2行目のCreateでしか設定できず、
となると、また新しくWebRequestのインスタンスが作られ、
別の接続になるため、上記のKeepAlive=true が生きていないです。

KeepAlive=true で、2回目のリクエストはどう出しますか?
よろしくお願いします。

回答

4行目に、KeepAlive=true で、理論上は、通信チャンネルが持続して、
2回目以降のリクエストも同じ接続になりますが、

ならないです。あくまで「できたら閉じずに接続使いまわしてねー」程度の申告をサーバーにしているだけです。使い回すかどうかはサーバー次第です。
(例えばブラウザでページ内のたくさんの画像リクエストをしたとして、二つ目、三つ目は大体一つ目とは違うコネクションでやってると思います。)

そして申告はリクエスト単位に(Connection: HTTPヘッダで)行います。

ですので新たにリクエストを作成して送信すればOKです。
なお、相手がHTTP/1.1対応なら自動的にtrueになります。

なお、サンプルではKeepAliveしない方法を二種類提示してますね、
keepaliveをFalseにすればたぶん
Connecion: Closeヘッダがつくと思いますので、
Connection = "Close"と同じ結果になるはず。

編集 履歴 (0)
  • クライアント側のServicePointManagerで制御を行っているとの解説もあります。ご回答ありがとうございました。 -
  • クライアント側「も」、サーバ側「も」、KeepAlive をサポートしている必要がある、という意味で、クライアント側だけの都合で KeepAlive できる、という意味ではないですよ -
  • ServicePointManager はあくまでクライアント側の設定で、サーバ側は Apache とか Nginx で設定されている必要があります -
  • 補足ありがとうございます。クライアント側は(.NETが)透過的にやってくれるものとしてサーバー側の話を書きましたが、質問の関心事はクライアントで新しいインスタンス作っても何故維持されるのかでしたので私の回答では説明不足でしたね。 -

質問の意図としては

  1. HttpWebRequestの同じインスタンスでなければ同じTCP接続が使いまわされない
  2. インスタンス作成時にしか URL が指定出来ない
  3. よって、同じ URL でしか接続が使いまわされない

ということでしょうか?

であれば 1 番が誤りで、同じインスタンスでなくても接続先が同じ(かつ接続先がKeepAliveをサポートしていれば)同じ接続が使いまわされます。


言い換えると、KeepAliveを false にしなければHttpWebRequestのインスタンスを破棄してもアプリの終了までサーバとの接続が維持されたままになることがあります。

どれぐらいの時間接続を維持するか、とか、どれぐらいの接続数を維持するか、とかの制御はServicePointManagerで行います。

編集 履歴 (0)
  • なるほど。分かりました。ご回答ありがとうございました。 -
ウォッチ

この質問への回答やコメントをメールでお知らせします。