我一直致力于开发某种中间人应用程序,它使用一系列日期(通常一次 7 个)的 HTTP post 请求将文本上传到 CMS 后端。我正在使用 HttpWebRequest 来完成此操作。第一次约会似乎工作正常,但是当它开始第二次约会时,我得到 System.Net.WebException: The request was aborted: The request was canceled.
找了一圈,发现了以下大线索:
http://www.jaxidian.org/update/2007/05/05/8
http://arnosoftwaredev.blogspot.com/2006/09/net-20-httpwebrequestkeepalive-and.html
他们并没有提供太多帮助。我试过重载 GetWebReuqest 但这没有意义,因为我没有使用该功能。
这是我的代码: http://pastebin.org/115268
至少成功运行一次后,我在第 245 行收到错误。
如果我能得到任何帮助,我将不胜感激,因为这是我从事了一段时间的项目的最后一步。这是我的第一个 C#/VS 项目,所以我愿意接受任何提示,但我想专注于首先解决这个问题。
谢谢!
网上列出的常见解决方案似乎是将HttpWebRequest 的KeepAlive 属性设置为false。如果根本原因是连接预计会被重用,即使它实际上在一段时间后自动关闭,这也可以解决问题。但是,不断打开和关闭连接会影响性能。
我遇到这个问题时使用的另一种可能的解决方案是扩展超时属性:WebRequest.ReadWriteTimeout、WebRequest.Timeout、RequestStream.WriteTimeout 和 RequestStream.ReadTimeout。请注意这些以毫秒为单位,因此您可能希望超时为 1000 * 60 * 10 以表示 10 分钟(如果您认为您会知道这意味着什么,则只需 600000 ...)。您可以通过减小文件大小来测试这是否是更可能导致问题的原因。
顺便说一句。您的代码已不在列出的网站上。如果问题仍然存在,您可能希望将其包含在帖子的正文中。
这是唯一适合我的解决方案:
这些行是关键:
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(yourUri);
wr.KeepAlive = false;
wr.Timeout = System.Threading.Timeout.Infinite;
wr.ProtocolVersion = HttpVersion.Version10;
在这里:
wr.AllowWriteStreamBuffering = false;
我的申请的简要总结: 我有多达 16 个相同的线程同时执行 HTTP 请求。这些线程中的每一个都从不同的网络服务器以及唯一的本地端点请求。现在进行这些调用的函数有 3 个连续的 HTTP 请求(对同一个网络服务器)并进行一些聚合。
根据上面链接中发布的解决方案,以下组合对我有用。
System.Net.ServicePointManager.DefaultConnectionLimit = 200;
System.Net.ServicePointManager.MaxServicePointIdleTime = 2000;
System.Net.ServicePointManager.MaxServicePoints = 1000;
System.Net.ServicePointManager.SetTcpKeepAlive(false, 0, 0);
HttpWebRequest webRequest1 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
+ "/xslt?");
webRequest1.KeepAlive = false;
webRequest1.Timeout = 2000;
//Do other stuff here...
//Close response stream
Thread.Sleep(1000); //This delay seems to help. Obviously very specific to the server
HttpWebRequest webRequest2 = (HttpWebRequest)WebRequest.Create("http://" + gatewayIP
+ "/xslt?");
webRequest2.KeepAlive = false;
webRequest2.Timeout = 2000;
//Do other stuff here...
//and so on...
我支持 Azure Web 服务,该服务正在接受来自移动应用程序的文件并将它们传输到 Azure blob 存储,方法是将传入请求的流复制到传出 HttpWebRequest 的流,例如
using (Stream requestStream = outgoingRequest.GetRequestStream())
{
context.Request.InputStream.copyTo(requestStream)
requestStream.Flush();
requestStream.Close();
}
每隔一段时间它就会在 Close() 期间或在使用 {} 结束时抛出“请求被中止:请求被取消”异常,如果您不包含 Close()。我尝试了上面所有建议的解决方案,但在我找到我想在这里分享的错误的实际原因之前,它们都没有奏效:有时传入请求的 InputStream 被切断并且不包含完整的文件内容。当这个不完整的流被复制到传出请求的流时,传出请求在 Close() 期间或在使用 {} 块的末尾抛出错误。这有点误导,因为原因不是传出请求而是
不完整的流被复制到它。
避免这种情况的方法是添加对传入请求流长度的检查,比较需要存储在调用应用程序标头中的文件长度,例如
if (context.Request.InputStream.Length != int.Parse(context.Request.Headers["file-length"]))
{
// handle this case here, e.g.
context.Response.StatusCode = 500;
context.Response.StatusDescription = "(500) Internal Server Error";
context.Response.End();
}
else
{
// proceed with copying the stream (the first code snippet)
}