c# – 在切换到IIS8后删除连接时ASP.NET处理请求
我有一个使用WebForms的ASP.NET 3.5应用程序,目前它正在IIS6上托管.一切都很棒.
但是,在切换到安装了IIS8的Windows 2012服务器后,我们会间歇性地获取截断请求.大多数情况下,这在事件日志中的视图状态异常中显示,但是,对于没有ViewState的表单,我们会得到不完整的帖子(最后几个字段缺失/部分截断). 这成了问题,我们升级到微软支持,经过数周的调试,他们说这是II7及以上的“正确”行为.他们的解释是IIS管道从6改为7. IIS6及以下将在将整个请求传递给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)因为你写了代码.您不应该有不完整的请求,因为请求可能是一个重要的数据,您需要发回一个错误,说明处理请求时出现问题,否则发布方只是看到请求已经神秘地消失了. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |