我在外部服务器(IIS)上部署了客户端桌面应用和Web服务。它们之间的通信基于HttpWebRequest和HttpWebResponse。 此代码在IIS 8.0上正常工作,并在将其升级到IIS 8.5之后将响应发送回客户端停止工作。客户端抛出以下异常:
System.IO.IOException:无法从传输中读取数据 连接:
现有连接被强行关闭 远程主机。 --->
System.Net.Sockets.SocketException:
An 现有连接被远程主机强制关闭 System.Net.Sockets.Socket.Receive(Byte []缓冲区,Int32偏移量,Int32 size,SocketFlags socketFlags)
在 System.Net.Sockets.NetworkStream.Read(Byte []缓冲区,Int32偏移量, Int32尺寸)
---内部异常堆栈轨迹的终点---
在System.Net.ConnectStream.Read(Byte []缓冲区,Int32偏移量,Int32 size)在System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)
在 Test.TestHttpService.GetResponseString(HttpWebResponse response)
在服务器端,不会抛出任何异常。服务器上的Wireshark和客户机上的Fiddler也没有任何线索。 IIS跟踪日志显示所有数据已成功发送到客户端
客户端代码:
public static string GetResponse(string serviceUrl, string resourceUrl, string method, string xmlRequestBody, string authorization, string connectionName)
{
string responseMessage = null;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
var request = HttpWebRequest.Create(string.Concat(serviceUrl, resourceUrl)) as HttpWebRequest;
if (request != null)
{
request.ContentType = "application/xml";
request.Method = method;
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.Timeout = int.MaxValue;
//request.ServicePoint.ConnectionLimit = 1;
request.Headers.Add("Authorization", authorization);
request.Headers.Add("ConnectionName", connectionName);
}
if (xmlRequestBody != null)
{
byte[] requestBodyBytes = TBCCompressionService.Zip(xmlRequestBody.ToString());
request.ContentLength = requestBodyBytes.Length;
if (request.ContentLength > 0)
{
using (Stream postStream = request.GetRequestStream())
{
postStream.Write(requestBodyBytes, 0, requestBodyBytes.Length);
}
}
}
if (request != null)
{
System.Net.ServicePointManager.Expect100Continue = false;
try
{
var response = request.GetResponse() as HttpWebResponse;
if (response.StatusCode == HttpStatusCode.OK)
{
responseMessage = GetResponseString(response);
}
else
{
responseMessage = response.StatusDescription;
}
}
catch(WebException ex)
{
var httpResponse = ex.Response as HttpWebResponse;
if (httpResponse != null
&& httpResponse.StatusCode == HttpStatusCode.BadRequest)
{
responseMessage = GetResponseString(ex.Response as HttpWebResponse);
}
else
{
throw ex;
}
}
}
return responseMessage;
}
private static string GetResponseString(HttpWebResponse response)
{
string result = string.Empty;
if(response != null)
{
using (Stream responseStream = response.GetResponseStream())
{
if (responseStream != null)
{
using (MemoryStream memoryStream = new MemoryStream())
{
//this is the line when above exception is thrown.
responseStream.CopyTo(memoryStream);
result = TBCCompressionService.UnZip(memoryStream.ToArray());
}
}
}
}
return result;
}
服务器端代码:
public static void Send(string responseContent, HttpStatusCode? httpStatus)
{
HttpResponse response = HttpContext.Current.Response;
int waitCounter = 1000;
if (response.IsClientConnected)
{
response.Clear();
response.BufferOutput = true;
response.Buffer = true;
if (httpStatus != null)
{
response.StatusCode = (int)httpStatus.Value;
}
if (responseContent == null
|| string.IsNullOrWhiteSpace(responseContent))
{
response.StatusCode = (int)HttpStatusCode.NoContent;
}
else
{
byte[] responseContentZip = Zip(responseContent);
int responseContentLength = responseContentZip.Length;
response.ContentType = "text/xml";
response.AppendHeader("Content-Length", responseContentLength.ToString());
response.BinaryWrite(responseContentZip);
}
response.Flush();
//If this sleep is not present exception is thrown on the client side
//Unable to read data from the transport connection : An existing connection was forcibly closed by the remote host.
System.Threading.Thread.Sleep(waitCounter);
response.Close();
response.End();
}
else
{
logger.Error("Client was no longer connected to remote server. Response wasn't sent.");
}
}
非常奇怪的是,正在睡眠的AppPool线程可以帮助并让响应成功地到达客户端。 在我看来Flush操作在连接关闭之前并没有结束,我在 System.Web.dll 代码中寻找了一些线索,但没有任何东西指出Flush在这种情况下是异步执行的执行期间的某些事情打破了连接。
答案 0 :(得分:0)
U CAN USE限制服务点数
** webRequest.ServicePoint.ConnectionLimit = 1;
**