IIS Web响应连接强制关闭问题

时间:2017-03-09 12:53:46

标签: c# .net iis httpwebrequest httpresponse

我在外部服务器(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跟踪日志显示所有数据已成功发送到客户端

enter image description here

客户端代码:

    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在这种情况下是异步执行的执行期间的某些事情打破了连接。

1 个答案:

答案 0 :(得分:0)

U CAN USE限制服务点数

  

**   webRequest.ServicePoint.ConnectionLimit = 1;

**