c# – 在切换到IIS8后删除连接时ASP.NET处理请求

前端之家收集整理的这篇文章主要介绍了c# – 在切换到IIS8后删除连接时ASP.NET处理请求前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个使用WebForms的ASP.NET 3.5应用程序,目前它正在IIS6上托管.一切都很棒.

但是,在切换到安装了IIS8的Windows 2012服务器后,我们会间歇性地获取截断请求.大多数情况下,这在事件日志中的视图状态异常中显示,但是,对于没有ViewState的表单,我们会得到不完整的帖子(最后几个字段缺失/部分截断).

这成了问题,我们升级到微软支持,经过数周的调试,他们说这是II7及以上的“正确”行为.他们的解释是IIS管道从6改为7.

IIS6及以下将在将整个请求传递给Asp.net之前缓冲整个请求,将忽略截断的请求.
IIS7及更高版本会在发送初始标头后将请求发送到Asp.net,由应用程序来处理截断的请求.

当存在连接问题(用户在传输期间拔出电缆)或者用户在帖子期间按下停止/重新加载页面时,这就成为问题.

在我们的HTTP日志中,我们看到与截断的请求相关的“connection_dropped”消息.

我很难相信这种行为是有意的,但我们已经在几个不同的服务器上进行了测试,并在IIS7及更高版本(Windows 2008,2008 R2和2012)中获得了相同的结果.

我的问题是:

1)这种行为甚至有意义吗?

2)如果这是“正确”的行为,您如何保护您的应用程序免于可能处理不完整的数据?

3)为什么应用程序开发人员有责任检测不完整的请求?假设,为什么app开发人员会处理不完整的请求而不是忽略它?

更新

我写了一个小的asp.net应用程序和网站来演示这个问题.

服务器

Handler.ashx.cs

public class Handler : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        if (context.Request.HttpMethod == "POST")
        {
            var lengthString = context.Request.Form["Length"];
            var data = context.Request.Form["Data"];

            if (lengthString == null)
            {
                throw new Exception("Missing field: Length");
            }

            if (data == null)
            {
                throw new Exception("Missing field: Data");
            }

            var expectedLength = int.Parse(lengthString);

            if (data.Length != expectedLength)
            {
                throw new Exception(string.Format("Length expected: {0},actual: {1},difference: {2}",expectedLength,data.Length,expectedLength - data.Length));
            }
        }

        context.Response.ContentType = "text/plain";
        context.Response.Write("Hello World,Request.HttpMethod=" + context.Request.HttpMethod);
    }

    public bool IsReusable
    {
        get { return false; }
    }
}

客户

Program.cs中

static void Main(string[] args)
{
    var uri = new Uri("http://localhost/TestSite/Handler.ashx");
    var data = new string('a',1024*1024); // 1mb

    var payload = Encoding.UTF8.GetBytes(string.Format("Length={0}&Data={1}",data.length,data));

    // send request truncated by 256 bytes
    // my assumption here is that the Handler.ashx should not try and handle such a request
    Post(uri,payload,256);
}

private static void Post(Uri uri,byte[] payload,int bytesToTruncate)
{
    var socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp)
    {
        // this allows us to disconnect unexpectedly
        LingerState = new LingerOption(true,0)
    };

    socket.Connect(uri.Host,uri.Port);

    SendRequest(socket,uri,bytesToTruncate);

    socket.Close();
}

private static void SendRequest(Socket socket,Uri uri,int bytesToTruncate)
{
    var headers = CreateHeaders(uri,payload.Length);

    SendHeaders(socket,headers);

    SendBody(socket,Math.Max(payload.Length - bytesToTruncate,0));
}

private static string CreateHeaders(Uri uri,int contentLength)
{
    var headers = new StringBuilder();

    headers.AppendLine(string.Format("POST {0} HTTP/1.1",uri.PathAndQuery));
    headers.AppendLine(string.Format("Host: {0}",uri.Host));
    headers.AppendLine("Content-Type: application/x-www-form-urlencoded");
    headers.AppendLine("User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/99.0");
    headers.AppendLine("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
    headers.AppendLine("Connection: Close");
    headers.AppendLine(string.Format("Content-Length: {0}",contentLength));

    return headers.ToString();
}

private static void SendHeaders(Socket socket,string headers)
{
    socket.Send(Encoding.ASCII.GetBytes(headers));
    socket.Send(Encoding.ASCII.GetBytes("\n"));
}

private static void SendBody(Socket socket,int numBytesToSend)
{
    socket.Send(payload,numBytesToSend,SocketFlags.None);
}

解决方法

1)如果您正在为集成模式下为其分配3.5应用程序的应用程序池运行管道,则可能无法处理请求的处理方式 due to ISAPI behavior.您可能正在生成它无法正确理解的请求,然后它会截断它们是默认值.您是否尝试在经典模式下运行应用程序池?

2)功能测试.大量的功能测试.创建测试工具并进行应用程序可以进行的所有调用,以确保其正常工作.这不是100%的解决方案,但实际上并非如此.有许多计算机科学论文解释了为什么不可能测试你的应用程序运行based on the Halting Problem的每一种可能情况.

3)因为你写了代码.您不应该有不完整的请求,因为请求可能是一个重要的数据,您需要发回一个错误,说明处理请求时出现问题,否则发布方只是看到请求已经神秘地消失了.

猜你在找的C#相关文章