1

我在这里遇到了一个非常奇怪的问题:

Web 服务器上有一个 RESTfull Web 服务Python Paste,WPF .net 应用程序每 2 秒向服务器发出一个 http POST 请求。问题是在第二次调用服务器时,请求超时!有时稍后(说第四次或第五次)请求会再次工作,然后我会再次遇到这个“超时”异常!

IntelliTrace 显示在 中存在阻塞操作ws2_32.dll

对 WSACancelBlockingCall 的调用中断了阻塞操作

我使用 IIS 模拟了 REST Web 服务器,asp.net问题不再存在,所以我认为它可能是 Python 服务器配置!但是当我从浏览器中发出请求时,Python Web 服务器正常工作!

但是我在 .net 客户端应用程序中尝试了不同的方法:

  • 我增加了 ServicePoint 的DefaultConnectionLimit

    ServicePointManager.DefaultConnectionLimit = 500;

  • 我为对服务器的任何新请求创建了一个新线程,并在请求完成时中止了它!

  • AppDomain在任何请求之前创建了一个新的,并在处理完成后明确卸载它!

  • 尝试了不同的http请求头:connection=keep-alive, accept=*

以上似乎都不起作用!GetRequestStream()然而有趣的是,当我在 VS 2012 中为该行设置断点时,请求不会超时并且可以正常工作!

使用反射调试 .net 托管代码我发现非托管recv方法ws2_32.dll导致操作阻塞,因此 Web 请求超时!

这是 C# 代码:

static void Main(string[] args)
{
    Task.Run(() =>
    {
        while (true)
        {
            Thread.Sleep(2000);
            Console.WriteLine(PostData());
        }
    });

    Console.ReadLine();
}

public static string PostData()
{
    try
    {
        var response = "";
        var httpRequest = WebRequest.CreateHttp("http://remote_address");
        httpRequest.ServicePoint.ConnectionLimit = 500;
        httpRequest.Method = "POST";
        httpRequest.ContentType = "application/x-www-form-urlencoded";
        httpRequest.Timeout = 5000;

        using (var writer = new StreamWriter(httpRequest.GetRequestStream()))
        {
            writer.Write("req=" + "[some parameters]");
        }

        using (WebResponse httpResponse = httpRequest.GetResponse())
        {
            using (var data = httpResponse.GetResponseStream())
            {
                StreamReader sr = new StreamReader(data, Encoding.UTF8);
                response = sr.ReadToEnd();
            }

            httpResponse.Close();
        }

        return response;
    }
    catch (WebException ex)
    {
        return "time out!";
    }
}

我能做些什么来完成这项工作吗?

4

1 回答 1

1

我设法解决了禁用Expect100Continue标头的问题:

ServicePointManager.Expect100Continue = false;

根据HTTP 1.1协议,当发送此标头时,使用 POST 方法的客户端请求期望收到100-Continue来自服务器的响应,指示客户端应该发送要发布的数据。

将此属性设置为true(这是 .Net 的默认行为),数据不会随初始请求一起发送。相反,此标头会发送到 Web 服务器,100-Continue如果实施正确,该服务器会响应。但是,并非所有 Web 服务器都能正确处理此问题,包括我尝试向其发布数据的服务器。我使用嗅探标头Fiddler并注意到我的代码确实发送了此标头,而Python Paste没有!

于 2012-11-15T16:29:35.683 回答