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



我在外部服务器(IIS)上部署了客户端桌面应用程序和Web服务。它们之间的通信基于HTTPWebrequest和HTTPWebresponse。该代码在IIS 8.0上运行正常,将其升级到IIS 8.5后,将响应发送给客户端停止工作。以下例外被抛在客户端:

system.io.ioexception:无法从传输中读取数据 连接:
现有的连接被强制关闭 远程主机。--->
system.net.sockets.socketException:
现有连接被远程主机强行关闭
at system.net.sockets.socket.receive(byte []缓冲区,int32 offset,int32 尺寸,socketflags socketflags)
at system.net.sockets.networkStream.Read(byte [] buffer,int32 offset, int32 size)
----内部异常堆栈跟踪---

at System.net.connectStream.Read(byte [] buffer,int32 offset,int32 尺寸)
在System.IO.Stream.internalCopyto(流目的地, int32缓冲)
at test.testhttpservice.getResponseString(httpwebresponse响应)

在服务器端,没有例外。服务器上的Wireshark和客户端计算机上的提琴手也没有任何线索。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线程会有所帮助,并让响应成功地到达客户端。在我看来,冲洗操作在连接之前没有结束,我在 system.web.dll 代码中寻找一些线索执行打破连接。

你可以使用限制服务点的数量

** webrequest.servicepoint.connectionlimit = 1;

**

最新更新