异常:“请求被中止:连接意外关闭”调用两个方法时相同的对象
Posted
技术标签:
【中文标题】异常:“请求被中止:连接意外关闭”调用两个方法时相同的对象【英文标题】:Exception:"The request was aborted: The connection was closed unexpectedly" When invoking two methods same object 【发布时间】:2013-07-24 21:14:05 【问题描述】:我遇到了很多人都遇到过的问题,但所有在线可用的解决方案都针对他们的场景。我已经尝试了可用的建议,但我尝试过的仍然没有运气:
1.) req.KeepAlive = false;
2.) req.ProtocolVersion = HttpVersion.Version10; (this solved a different exception that I was getting)
我有两种方法将 XML 字符串传递给服务器并返回响应,这两种方法是:
public string userDeviceQuery(string userID)
string query = "xml=<query>";
query += "<appInfo>";
query += "<appID>" + appID + "</appID>";
query += "<appCertificate>" + appCertificate + "</appCertificate>";
query += "</appInfo>";
query += "<userDevicesQuery>";
query += "<userID>";
query += userID;
query += "</userID>";
query += "</userDevicesQuery>";
query += "</query>";
using (Stream str = req.GetRequestStream())
str.Write(System.Text.Encoding.ASCII.GetBytes(query), 0, query.Length);
WebResponse res = req.GetResponse();
string stringResponse;
using (StreamReader reader = new StreamReader(res.GetResponseStream()))
stringResponse = reader.ReadToEnd();
string result = parseDeviceQueryRes(stringResponse);
return result;
与
public void logoutOfEM(string deviceName)
string lgRequest = "xml=<request>";
lgRequest += "<appInfo>";
lgRequest += "<appID>" + appID + "</appID>";
lgRequest += "<appCertificate>" + appCertificate + "</appCertificate>";
lgRequest += "</appInfo>";
lgRequest += "<logout>";
lgRequest += "<deviceName>";
lgRequest += deviceName;
lgRequest += "</deviceName>";
lgRequest += "</logout>";
lgRequest += "</request>";
using (Stream str = req.GetRequestStream())
str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
WebResponse res = req.GetResponse();
using (StreamReader reader = new StreamReader(res.GetResponseStream()))
stringResponse = reader.ReadToEnd();
string stringResponse = reader.ReadToEnd();
它们都是名为 EMAPI 的类的一部分。我可以单独使用这两种方法,但是如果尝试将它们与表示 EMAPI 的相同对象背靠背使用,我会得到上述异常。我不确定是什么导致连接关闭,如果可能的话,我希望能够保持打开状态并使用解构器关闭它。
对于那些好奇此代码处理 Cisco Extension Mobility API 的人,第一种方法查询服务器以获取您登录的设备,第二种方法将用户从该设备注销。
感谢您的帮助。
【问题讨论】:
在一个不相关的注释中,我会使用 stringbuilder 在构造巨大的 + 字符串时提高效率。 您能否详细说明一下,为什么 StringBuidler 在连接字符串时更好? dotnetperls.com/stringbuilder-performance 第一次通话后有没有检查连接状态。可能是远程服务器关闭了连接。 哦,哇,我的代码中有大约 15 个使用字符串的查询,我将全部修复。这可以解决我正在经历的缓慢。塔恩克斯!! 【参考方案1】:为每种方法使用不同的 HttpWebRequest。您不应该为不同的请求重用 HttpWebRequest 对象。检查这个:Can I reuse HttpWebRequest without disconnecting from the server?。在内部,.NET 可以决定尽可能重用与同一服务器的连接,但服务器可以决定在每次请求后关闭连接,即使您指定 req.KeepAlive = true。
还要确保在方法中处置/关闭 WebResponse 对象。
【讨论】:
我只是将它设置为 false 只是为了尝试来自不同线程的建议,我尝试了 'true' 和 'false' 我更新了我的答案,你不应该为不同的请求重复使用 HttpWebRequest。 谢谢,这就是问题所在。【参考方案2】:我会首先在我的所有 IDisposables 周围使用“使用”关键字。其次,看起来您将 StreamReaders 保持打开状态。
编辑
回答您关于使用关键字的评论。
而不是这个:
Stream str = req.GetRequestStream();
str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
str.Close();
这样写:
using(Stream str = req.GetRequestStream())
str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
using 关键字会自动为您处理所有 IDisplosable 任务。
我刚刚注意到您的代码以及为什么我认为您没有关闭。您正在调用 close ,然后尝试准备线路。这是一个很好的例子,说明了为什么要养成使用“using”关键字的习惯。
StreamReader reader = new StreamReader(res.GetResponseStream());
reader.Close(); //Calling CLOSE before trying to use the reader
string stringResponse = reader.ReadToEnd();
另一个编辑
public void logoutOfEM(string deviceName)
string lgRequest = "xml=<request>";
lgRequest += "<appInfo>";
lgRequest += "<appID>" + appID + "</appID>";
lgRequest += "<appCertificate>" + appCertificate + "</appCertificate>";
lgRequest += "</appInfo>";
lgRequest += "<logout>";
lgRequest += "<deviceName>";
lgRequest += deviceName;
lgRequest += "</deviceName>";
lgRequest += "</logout>";
lgRequest += "</request>";
using (Stream str = req.GetRequestStream())
str.Write(System.Text.Encoding.ASCII.GetBytes(lgRequest), 0, lgRequest.Length);
WebResponse res = req.GetResponse();
var response = string.Empty;
using(StreamReader reader = new StreamReader(res.GetResponseStream()))
response = reader.ReadToEnd();
【讨论】:
我确实关闭了所有 StreamReader,但这并没有帮助我不确定您指的是什么“首先在我的所有 IDisposables 周围使用 'using' 关键字” 这就是为什么我们应该这样做,但它仍然没有解决问题,我已经在问题中更新了我的代码 在您编辑的问题中,您仍在调用 reader.Close() 在方法 logoutOfEM 中关闭阅读器后尝试使用阅读器 在这两种方法中它是一个不同的阅读器,我正在创建一个阅读器并在它们中关闭它 是的,但你还是不明白。在方法 logoutOfEM 中执行 ReadToEnd() 之前,您正在调用 close。我在编辑中更正了它。以上是关于异常:“请求被中止:连接意外关闭”调用两个方法时相同的对象的主要内容,如果未能解决你的问题,请参考以下文章