我在外部服務器(IIS)上部署了客戶端桌面應用程序和Web服務。它們之間的通信基於HttpWebRequest和HttpWebResponse。 此代碼在IIS 8.0上正常工作,並將其升級到IIS 8.5後,將響應發送回客戶端停止工作。下面拋出異常在客戶端:IIS網頁響應連接強制關閉問題
System.IO.IOException:無法從傳輸 連接讀取數據:
一個現有的連接強制關閉由 遠程主機。 --->
System.Net.Sockets.SocketException:
一個 現有連接被遠程主機強制關閉
在 System.Net.Sockets.Socket.Receive(Byte []緩衝區,Int32偏移量,Int32 大小,的SocketFlags的SocketFlags)
在 System.Net.Sockets.NetworkStream.Read(字節[]緩衝液,的Int32偏移, 的Int32大小)
---內部異常堆棧跟蹤的結尾---
在System.Net.ConnectStream .Read(Byte []緩衝區,Int32偏移量,Int32 大小)
at System.IO.Stream.InternalCopyTo(Stream destination, Int32 bufferSize)
at Test.TestH ttpService.GetResponseString(HttpWebResponse響應)
在服務器端不會引發異常。服務器上的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在這種情況下是異步執行的,或者是在執行期間中斷連接。
你看事件日誌? –
是的,我做了,也沒有線索這個連接發生了什麼。 – RadMi