- PR -

C#でwebサーバーにPOSTでリクエストを投げても情報の取得がうまくいきません。

投稿者投稿内容
kitakita
会議室デビュー日: 2007/06/13
投稿数: 5
投稿日時: 2007-06-14 15:44
れいさんご返信ありがとうございます。

.NET Framework 1.1で開発しているためか、ServicePointクラスに
Expect100Continueプロパティが見つかりませんでしたので、以下のコードを
関数の最初に加えてみました。

コード:
System.Net.ServicePointManager.Expect100Continue = false;

その結果、プロキシ越えでも正常にPOSTの応答を取得できました。
ありがとうございました。

引用:

ただしいHTTP1.1プロキシを用いるのがいいと思いますが、
どうしてもExpectヘッダーを除きたい場合は
以下のコードを関数の最初で呼べばいけます。

コード:
ServicePointManager.FindServicePoint( url ).Expect100Continue = false;



いろいろ問題が発生します。
覚悟の上でどうぞ。



現在作成しているアプリケーションは、不特定多数の方に配ることを想定していますので、
ただしいHTTP1.1プロキシを使われることが保証できません。
そのため、現在ではExpect100Continueをfalseにする方向を検討しています。

その際、開発中のアプリケーションで送るPOSTのリクエスト先もこちらで用意したものに
する予定ですし、POSTで送るデータ自身もさほど大きなものにはならない予定ですので、
Expectヘッダーの使い道である、

リクエスト先のサーバーと通信ができるかどうかを確かめる

というフェイズは無視できる = Expect100Continueを常にfalseにして
POSTを行っても問題はないという認識でいるのですが、これは誤りでしょうか?
(実際、同様のコンセプトで運用している、Javaで作成したアプリケーションは、
少なくとも表面上は問題なく動作しています)

もし誤りでしたら、何かExpectヘッダーを省くことで生じる不具合に関する
参考URLなど、ご教示願えないでしょうか。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-06-14 18:13
引用:

.NET Framework 1.1で開発しているためか、ServicePointクラスに
Expect100Continueプロパティが見つかりませんでしたので、以下のコードを



あれれ?
http://msdn2.microsoft.com/ja-jp/library/system.net.servicepoint.expect100continue(vs.80).aspx
1.1でもあると書いてあるんですがねぇ。
間違い?

引用:

関数の最初に加えてみました。



ServicePointManagerをセットしてしまうなら
アプリケーションの最初で1回。
FindServicePointを使うならURIのAuthorityが変わるたびに1回。
がベストです。
大して変わりませんが。

引用:

リクエスト先のサーバーと通信ができるかどうかを確かめる
というフェイズは無視できる = Expect100Continueを常にfalseにして
POSTを行っても問題はないという認識でいるのですが、これは誤りでしょうか?
(実際、同様のコンセプトで運用している、Javaで作成したアプリケーションは、
少なくとも表面上は問題なく動作しています)



はい。本来はその認識で正しくあるべきだと思います。
が、実際には問題が発生します。設計の問題が大きいです。

引用:

もし誤りでしたら、何かExpectヘッダーを省くことで生じる不具合に関する
参考URLなど、ご教示願えないでしょうか。



URLを覚える特殊技能は持っていませんし、
ネットで仕入れた情報なら、kitakitaさんご自身でも検索できるでしょう。

私が自分で調べた結果は、かなり条件が絡んでいるので、
説明するのはめんどくさいです。
なぜうまくいかなそうなのか、
漠然と説明するくらいで勘弁してください。

実際、いろいろやって動くならいいと思いますし。

要約すると4件。

ServicePointが共有される問題。
POSTのエラー時の問題。
認証の問題。
HTTPWebRequestが弱い問題。

ServicePointManagerはアプリケーションドメインで共有、
ServicePointは接続で共有です。
100Continueの設定も、共有です。
大きいプロジェクトや外部ライブラリ等を用いる場合はどうなるんでしょう?
ServicePointの接続数はたった2本です。(増やせますがそれも…)
余裕は1本しかありません。

POSTがエラーを返した場合、どうなるでしょう?
プロキシが入ってたりした場合、どうなりますか?
その場合接続で共有されるServicePointはどうなるんでしょう。
サーバーはDOSを防ぐためにエラーがあるとすぐに接続を切断したりしますが、
その場合ServicePointはきちんと再利用されるんでしょうか?

認証のメカニズムでは再送が頻繁に起こります。
認証エラーのときにメッセージを送信中の場合も多々あります。
きちんと認証情報を再送できるでしょうか?
これも同様に、接続で共有されるServicePointはどうなるんでしょう。

HTTPWebRequestは上記の再送を何回もマネージできないといけません。
そのたびに、内部バッファを送信します。
100Continueが送られてくることを仮定するとだいぶ楽になりませんか?


もし、問題が発生するなら、以下を試してください。

POSTのサイズはなるべく小さく

WebRequestにはConnectionGroupを設定し、
接続が終わるたびにServicePoint.CloseConnectionGroupでリセット

NTLM認証やNegotiate認証は使わず、
Basic認証でPreAuthenticate=Trueとするか、自分でBase64Encodingする。
Digestくらいなら.Netのサポートがありますから自分で実装できるでしょう。

認証失敗の再送は自分で行い、再送する前にCloseConnectionGroupする。

Content-Lengthをきちんとセット。
Connection: Closeを用いる。
Chunkedを使わない。

などなど。

もし、簡単なPOSTだけで、NTLMなどの高度な認証がいらないのでしたら、
SocketやTCPClientを使うことをお勧めします。
通信は一般に受けるのが難しいですが、送るのは楽です。
POSTだけならTCPClientで接続して
要求をだーっと流してやればそれでおしまいです。

返事は最初の1行みれば十分。
エラーが起きたら接続切ってやりなおし。
簡単です。
kitakita
会議室デビュー日: 2007/06/13
投稿数: 5
投稿日時: 2007-06-18 18:04
れいさんご返信ありがとうございます。
返事が遅くなってしまい、申し訳ありません。

引用:

あれれ?
http://msdn2.microsoft.com/ja-jp/library/system.net.servicepoint.expect100continue(vs.80).aspx
1.1でもあると書いてあるんですがねぇ。
間違い?


すみません。
完全に自分が誤って思い込んでいました。
自分の開発環境は1.0でした。

引用:

ServicePointが共有される問題。
POSTのエラー時の問題。
認証の問題。
HTTPWebRequestが弱い問題。


情報のご提供ありがとうございました。
正直に言って、完全に理解できたとは言いがたいのですが、頂いた情報を元に、調査・検討を重ねてみます。

この度はありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)