我遇到了一个非常奇怪的问题:
Python Paste
web服务器上有一个RESTfull web服务,WPF.net应用程序每2秒向服务器发出一个http POST请求。问题是,在对服务器的第二次调用中,请求超时!有时后来(比如第四次或第五次)再次要求工作,后来我又得到了这个"超时"的例外!
IntelliTrace显示ws2_32.dll
:中存在阻止的操作
阻塞操作被对的调用中断WSA取消阻止呼叫
我使用asp.net
模拟了IIS上的REST web服务器,但问题不再存在,所以我认为可能是Python服务器配置!但是当我在浏览器中发出请求时,Python Web服务器可以正常工作!
然而,我在.net客户端应用程序中尝试了不同的东西:
-
我增加了ServicePoint的
DefaultConnectionLimit
:ServicePointManager.DefaultConnectionLimit = 500;
-
我为服务器的任何新请求创建了一个新线程,并在请求完成后中止了它!
-
我在任何请求之前创建了一个新的
AppDomain
,并在处理完成后显式卸载它! -
尝试了不同的http请求标头:
connection=keep-alive, accept=*
以上似乎都不起作用!然而,有趣的是,当我在VS 2012中为GetRequestStream()
行设置断点时,请求不会超时并正常工作!
使用反射调试.net托管代码我发现ws2_32.dll
的非托管recv
方法导致操作阻塞,因此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!";
}
}
我能做些什么吗?
我设法通过禁用Expect100Continue
标头来解决问题:
ServicePointManager.Expect100Continue = false;
根据HTTP 1.1
协议,当发送该报头时,使用POST方法的客户端请求期望从服务器接收100-Continue
响应,以指示客户端应该发送要发布的数据。
如果将此属性设置为true
(这是.Net的默认行为),则数据不会与初始请求一起发送。相反,如果实现正确,则将此标头发送到web服务器,web服务器将以100-Continue
进行响应。但是,并非所有web服务器都能正确处理此问题,包括我试图向其发布数据的服务器。我使用Fiddler
嗅探了头部,注意到我的代码确实发送了这个头部,而Python Paste
没有!