web-dev-qa-db-ja.com

POSTを実行するときにHttpWebRequestタイムアウトを100秒より長く設定することはできませんか?

POSTを実行するときにHttpWebRequestが100秒を超えるタイムアウト値を尊重しないという問題が発生しています。ただし、要求がGETの場合、100秒を超えるタイムアウト値が尊重されます。タイムアウト例外は、.GetResponse()呼び出しでスローされます。検出できたすべてのタイムアウト値を設定していますが、タイムアウト値が欠落しているか、フレームワークにバグがあるようです。

これは、Visual Studio2008を使用して構築された.NETFramework 3.5を対象とするC#アプリです。WebサーバーはIIS 6.0で、接続タイムアウトはデフォルトの120秒に設定され、キープアライブが有効になっています。 。ここでも、GETリクエストは、指定したタイムアウト値を尊重します。POSTリクエストは、100秒未満の場合はタイムアウトを尊重します。

これが私のコードです:

int timeout = 200000; // 200 seconds
HttpWebRequest proxyRequest = (HttpWebRequest)WebRequest.Create(serverUrl);
proxyRequest.Accept = clientRequest.AcceptTypes.ToDelimitedString(", ");
proxyRequest.Method = "POST"
proxyRequest.UserAgent = clientRequest.UserAgent;
proxyRequest.Timeout =  timeout;
proxyRequest.ReadWriteTimeout = timeout;
proxyRequest.KeepAlive = false;
proxyRequest.AllowAutoRedirect = false;
proxyRequest.ServicePoint.Expect100Continue = false;
proxyRequest.ServicePoint.MaxIdleTime = timeout;
proxyRequest.ServicePoint.ConnectionLeaseTimeout = -1;

try
{
    // add post data
    request.ContentType = "application/x-www-form-urlencoded";
    byte[] postData = Encoding.UTF8.GetBytes("somedata=7&moredata=asdf");
    // set some post data
    request.ContentLength = postData.Length;
    using (Stream stream = request.GetRequestStream())
    {
        stream.Write(postData, 0, postData.Length);
        stream.Close();
    }

    // UPDATE
    // don't set Timeout here! It will be ignored
    // proxyRequest.Timeout = timeout;

    // Timeout exception thrown here if GetResponse doesn't return within 100 seconds
    // even though the Timeout value is set to 200 seconds.
    using (HttpWebResponse proxyResponse = (HttpWebResponse)proxyRequest.GetResponse())
    {
        using (Stream stream = proxyResponse.GetResponseStream())
        {
            using (StreamReader reader = new StreamReader(stream, Encoding.Default))
            {
                string content = reader.ReadToEnd();
                [other pointless code for this example]
                reader.Close();
            }
            stream.Close();
        }
        proxyResponse.Close();
    }
}
finally
{
    proxyRequest.Abort();
}

タイムアウト値を5秒に設定すると、予想どおり5秒後にタイムアウト例外が発生します。これは、タイムアウト値が完全に無視されていないことを示しています。

他の誰かがこの問題に遭遇しましたか? GetResponseの非同期バージョンを使用するとこの問題を回避できますか?どんな考えでも歓迎します、私はこれに数日間立ち往生しています。

[〜#〜]更新[〜#〜]

POSTは、データを投稿しない場合にタイムアウト値を尊重するように取得できます(これはあまり役に立ちません)。ただし、データを投稿するとすぐに、ContentLengthは> 0、100秒でタイムアウトします。また、プロキシは含まれません。

更新2

POSTデータを例に追加し、Timeoutプロパティを設定しない場所に関するコメントを追加しました

12
thein

私はそれを考え出した。これはDRYコーディングが戻ってきて、私を尻に噛み付く例です。上記のコードは私の実際のコードの言い換えであるため、上記のコードは正常に機能します。

問題は、proxyRequest.GetRequestStream()を呼び出してPOSTデータを追加した後、Timeout値を設定していたことです。 TimeoutプロパティとReadWriteTimeoutプロパティの両方を設定していた場合、最短のタイムアウトが優先されました。POSTリクエストの場合、フレームワークであってもGetRequestStreamの呼び出し後にタイムアウト値を設定すると、設定された値はすべて無視されます(代わりに、設定後にTimeoutプロパティを調べたところ、期待どおりに設定されていることが示されましたが、デフォルトの100秒が使用されました)。タイムアウトを設定したいのですが。プロパティは、ReadWriteTimeoutプロパティの設定と同じように機能しました。GetRequestStreamを呼び出した後にReadWriteTimeoutプロパティを設定しようとすると、例外がスローされます。Timeoutが同じことを行った場合は、かなりの時間を節約できます。これはもっと早くですが、私はそれを学習体験にチョークで書きます。

したがって、話の教訓は、HttpWebRequestを作成するときにすべてのタイムアウトプロパティを正しく設定することです。

24
thein

クライアントとサーバーの間にWebプロキシがありますか?おそらく、それはタイムアウト自体を使用しています。

Wireshark を使用して、ネットワークレベルで何が起こっているか、特に100秒でネットワーク上で何かが起こっているかどうかを確認することをお勧めします。

3
Jon Skeet