Webサーバーからのデータを記録するC#アプリケーションを開発しています。次の投稿要求をWebサーバーに送信し、応答を待ちます。
/// <summary>
/// Function for obtaining testCgi data
/// </summary>
/// <param name="Parameters"></param>
/// <returns></returns>
private string HttpmyPost(string Parameters)
{
string str = "No response";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriTestCGI);
request.Method = "POST";
byte[] bytes = Encoding.UTF8.GetBytes(Parameters);
request.ContentLength = bytes.Length;
Stream requestStream = request.GetRequestStream();
requestStream.Write(bytes, 0, bytes.Length);
requestStream.Close();
WebResponse response = request.GetResponse();
Stream stream = response.GetResponseStream();
StreamReader reader = new StreamReader(stream);
try
{
var result = reader.ReadToEnd();
stream.Dispose();
str = result.ToString();
reader.Dispose();
}
catch (WebException ex)
{
//System.Windows.Forms.MessageBox.Show(ex.Message);
System.Diagnostics.Trace.WriteLine(ex.Message);
}
finally
{
request.Abort();
}
return str;
}
エラーが発生しています
> "The underlying connection was closed: The connection was closed
> unexpectedly"
エラーのデバッグを試みましたが、Firefoxからの投稿要求を確認するためにフィドラーを使用しました。フィドラーが私のプログラムが完璧に機能していたときはいつでも驚いたことに。フィドラーを閉じると、同じエラーが発生します。
Fiddlerはプロキシとして機能しているため、設定の一部が変更される可能性があります。 webclientを使用してみましたが、結果は同じでした。
Pythonでリクエストをコーディングしようとすると、問題なくすべてが正常に機能しました。当然、IronPythonをインストールしてその特定の機能をラップするオプションがありますが、このやり過ぎとエレガントさの欠如を考慮して、よりリーンなアプローチを追求しています。これは設定の調整にすぎないと思われます。
私は修正を試みましたが、私の場合は無関心です。
request.Accept
request.ReadWriteTimeout
request.Timeout
request.UserAgent
request.Headers
request.AutomaticDecompression
request.Referer
request.AllowAutoRedirect
//request.TransferEncoding
request.Expect
request.ServicePoint.Expect100Continue
request.PreAuthenticate
request.KeepAlive
request.ProtocolVersion
request.ContentType
上記の調整の有無にかかわらず、Fiddlerがデータをキャプチャしているときにコードが機能します。
また、プログラムでエラーが発生することは注目に値するかもしれません
WebResponse response = request.GetResponse();
更新:@EricLawの提案に従って、レイテンシを調べました。私はこの記事を見つけました 間隔を追加するとHttpWebRequestが遅くなります これはNagleアルゴリズムの有効化を示唆しています。現在、閉じられた接続はありませんが、全体的な応答にはわずかな遅れがあります(非同期ではなくwinformsを使用する場合)。
Fiddlerがどのように「魔法のように」物事を修正できるかについて少し書きます: http://blogs.telerik.com/fiddler/posts/13-02-28/help!-running-fiddler-fixes-my- app-
発生している問題は、実際には.NET Framework自体のバグです。 HTTPのルールでは、最初の応答を送信した後、サーバーはいつでもKeepAlive接続を閉じることができます(たとえば、クライアントがKeepAlive動作を要求した場合でも、接続で別の要求を受け入れる必要はありません)。
.NETには、応答が完了した後に接続を閉じる場合にサーバーがConnection: close
応答ヘッダーを含めることを期待するバグがあります。サーバーがConnection: Close
ヘッダーなしで接続を閉じた場合(RFC2616で完全に有効)、. NETは接続で次の要求を送信しようとしたときに閉じられた接続を検出し、この例外をスローします。 .NETshouldが行うべきことは、静かに新しい接続を作成し、その新しい接続でリクエストを再送することです。
Fiddlerは、サーバーが接続を閉じてもかまわないため、この問題を解決し、クライアントへの接続を維持します。クライアントが2番目の要求を送信すると、Fiddlerはサーバーへの接続の再利用を試み、クライアントが閉じられたことに気づき、静かに新しい接続を作成します。
次の方法で、コード内のこの問題を軽減できます。
アプローチ#3は、サーバーを制御する場合にのみ機能します。また、クライアントは使用後に接続を閉じるゲートウェイ/プロキシの背後にある可能性があるため、おそらくアプローチ#2も使用する必要があります。
提案と質問:1)Wiresharkのインストールを実際に見たい場合。送受信されている内容を正確に表示します。そして、それはフィドラーと比較することを可能にします。 request.ContentType = "...."のようなヘッダーが欠落していると思いますが、wiresharkのみがどのヘッダーを表示するか(HttpWebRequestでは送信されず、代わりの代替手段を介して送信されます)を示します。
2)HTTP応答コンテンツ内でエラーが発生していますか?それは例外ですか?それが例外である場合は、catchでキャッチされますか、リクエスト中にtryステートメントの前に発生しますか?