zoukankan      html  css  js  c++  java
  • 【转】HttpRuntime的认识与加深理解

    原文:http://www.cnblogs.com/whtydn/archive/2009/10/16/1584418.html
     
    下面最先介绍HttpRuntime的Web.config里的配置
    复制代码
    <httpRuntime
       executionTimeout = "number" 
       maxRequestLength = "number" 
       requestLengthDiskThreshold = "number" 
       useFullyQualifiedRedirectUrl = "[True|False]" 
       minFreeThreads = "number" 
       minLocalRequestFreeThreads = "number" 
       appRequestQueueLimit = "number"
       enableKernelOutputCache = "[True|False]" 
       enableVersionHeader = "[True|False]" 
       apartmentThreading = "[True|False]"
       requireRootedSaveAsPath = "[True|False]"
       enable = "[True|False]" 
       sendCacheControlHeader = "[True|False]" 
       shutdownTimeout = "number"
       delayNotificationTimeout = "number"
       waitChangeNotification = "number" 
       maxWaitChangeNotification = "number" 
       enableHeaderChecking = "[True|False]" 
    />
    复制代码
    通过上面的配置说明, 下面是在Web.Config里节点的设置
    复制代码
    <configuration>
      <system.web>
      <httpRuntime maxRequestLength="4000"
        enable = "True"
        requestLengthDiskThreshold="512
        useFullyQualifiedRedirectUrl="True"
        executionTimeout="45"
        versionHeader="1.1.4128"/>
      </system.web>
    </configuration>
    复制代码

    IIS 所收到的对某 Microsoft ASP.NET 页面的每个请求都被移交给 ASP.NET HTTP 管线。HTTP 管线由一系列托管对象组成,这些对象按顺序处理该请求,并完成从 URL 到普通 HTML 文本的转换。HTTP 管线的入口点是 HttpRuntime 类。ASP.NET 基础结构为辅助进程中所承载的每个 AppDomain 创建此类的一个实例请注意,该辅助进程为当前正在运行的每个 ASP.NET 应用程序维护一个不同的 AppDomain。

    要激活 HTTP 管道,可以创建一个 HttpRuntime 类的新实例,然后调用其 ProcessRequest 方法。一个完整的页面请求会包括下面的流程:
    首先被WWW服务器截获(inetinfo.exe进程), 该进程首先判断页面后缀, 然后根据IIS中配置决定调用具体的扩展程序。aspx就会调用aspnet_isapi.dll, 
    然后由aspnet_isapi.dll发送给w3wp.exe(iis 工作者进程,IIS6.0中叫做 w3wq.exe,IIS5.0中叫做 aspnet_wp.exe)。

    接下来在w3wp.exe调用.NET类库进行具体处理,顺序如下:ISAPIRuntim, HttpRuntime, HttpApplicationFactory, HttpApplication, HttpModule, HttpHandlerFactory, HttpHandler

    ISAPIRuntime:主要作用是调用一些非托管代码生成HttpWorkerRequest对象,HttpWorkerRequest对象包含当前请求的所有信息,然后传递给HttpRuntime
    HttpRuntime:根据HttpWorkerRequest对象生成HttpContext,HttpContext包含request、response等属性, 再调用HttpApplicationFactory来生成IHttpHandler, 调用HttpApplication对象执行请求
    HttpApplicationFactory: 生成一个HttpApplication对象
    HttpApplication:进行HttpModule的初始化,HttpApplication创建针对此Http请求的 HttpContext对象
    HttpModule: 当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于HTTP请求来讲,HttpModule是一个HTTP请求的“必经之路”,所以可以在这个HTTP请求传递到真正的请求处理中心(HttpHandler)之前附加一些需要的信息在这个HTTP请求信息之上,或者针对截获的这个HTTP请求信息作一些额外的工作,或者在某些情况下干脆终止满足一些条件的HTTP请求,从而可以起到一个Filter过滤器的作用。
    HttpHandlerFactory:把用户request 转发到HttpHandlerFactory,再由HttpHandlerFactory实例化HttpHandler对象来相应request
    HttpHandle:Http处理程序,处理页面请求

    从上面看出HttpRuntime其中有一个ProcessRequest 方法
    public static void ProcessRequest(HttpWorkerRequest wr);  //驱动所有 ASP.NET Web 处理执行。伪代码如下:

    复制代码
    public static void HttpRuntime.ProcessRequest(HttpWorkerRequest wr)
     {
       // 检查当前调用者有没有作为ASP.NET宿主(Host)的权限
       InternalSecurityPermissions.AspNetHostingPermissionLevelMedium.Demand(); 

       if(wr == null)
       {
         throw new ArgumentNullException("custom");
       }

       RequestQueue queue = HttpRuntime._theRuntime._requestQueue;

       if(queue != null)
       {
         // 将参数中的Web页面请求放入请求队列中, 并从队列中使用FIFO策略获取一个页面请求
         wr = queue.GetRequestToExecute(wr);
       }

       if(wr != null)
       {     
         HttpRuntime.CalculateWaitTimeAndUpdatePerfCounter(wr); // 更新性能计数器     
          HttpRuntime.ProcessRequestNow(wr); // 实际完成页面请求工作
       }
     }
    复制代码

    ProcessRequestNow函数则直接调用缺省HttpRuntime实例的ProcessRequestInternal函数完成实际页面请求工作,伪代码如下:

    internal static void HttpRuntime.ProcessRequestNow(HttpWorkerRequest wr)
    {
       HttpRuntime._theRuntime.ProcessRequestInternal(wr);
    }

    ProcessRequestInternal函数逻辑稍微复杂一些,大致可分为四个部分:
    检查当前HttpRuntime实例是否第一次被调用,如果是第一次调用则通过FirstRequestInit函数初始化
    调用HttpResponse.InitResponseWriter函数初始化页面请求的返回对象HttpWorkerRequest.Response
    调用HttpApplicationFactory.GetApplicationInstance函数获取当前 Web 应用程序实例
    使用Web应用程序实例完成实际的页面请求工作
    伪代码如下:


    private void HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
     {
       // 构造 HTTP 调用上下文对象
       HttpContext ctxt = new HttpContext(wr, 0); 

       // 设置发送结束异步回调函数
       wr.SetEndOfSendNotification(this._asyncEndOfSendCallback, ctxt);

       // 更新请求计数器
       Interlocked.Increment(&(this._activeRequestCount));

       try
       {
         // 检查当前HttpRuntime实例是否第一次被调用
         if(this._beforeFirstRequest)
         {
           lock(this)
           {
             // 使用 Double-Checked 模式 避免冗余锁定
             if(this._beforeFirstRequest)
             {
               this._firstRequestStartTime = DateTime.UtcNow;
               this.FirstRequestInit(ctxt); // 初始化当前 HttpRuntime 运行时环境
               this._beforeFirstRequest = false;
             }
           }
         }

         // 根据配置文件设置,扮演具有较高特权的角色
         ctxt.Impersonation.Start(true, false);
         try
         {
           // 初始化页面请求的返回对象
           ctxt.Response.InitResponseWriter();
         }
         finally
         {
           ctxt.Impersonation.Stop();
         }

         // 获取当前 Web 应用程序实例
         IHttpHandler handler = HttpApplicationFactory.GetApplicationInstance(ctxt);

         if (handler == null)
         {
           throw new HttpException(HttpRuntime.FormatResourceString("Unable_create_app_object"));
         }

         // 使用Web应用程序实例完成实际的页面请求工作
         if((handler as IHttpAsyncHandler) != null)
         {
           IHttpAsyncHandler asyncHandler = ((IHttpAsyncHandler) handler);
           ctxt.AsyncAppHandler = asyncHandler;
           // 使用异步处理机制
           asyncHandler.BeginProcessRequest(ctxt, this._handlerCompletionCallback, ctxt);
         }
         else
         {
           handler.ProcessRequest(ctxt);
           this.FinishRequest(ctxt.WorkerRequest, ctxt, null);
         }
       }
       catch(Exception E)
       {
         ctxt.Response.InitResponseWriter();
         this.FinishRequest(wr, ctxt, E);
       }
     }

    HttpRuntime.ProcessRequestInternal函数中调用了HttpApplicationFactory.GetApplicationInstance函数获取当前 Web 应用程序实例。至少HttpRuntime已经完完成,将转进HttpApplicationFactory阶段流程。大家可以看到,围绕HttpRuntime的函数都有一个HttpWorkerRequest参数,下面简单介绍一下这个参数的作用。在ISAPIRuntime阶段,调用一些非托管代码生成HttpWorkerRequest对象,该对象包含当前请求的所有信息,然后传递给HttpRuntime,这里生成的HttpWorkerRequest对象可以直接在我们的页面里调用.
    IServiceProvider provider=(IServiceProvider)HttpContext.Current;
    HttpWorkerRequest wr=(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
    然后可以通过wr来调用里面的方法。关于HttpWorkerRequest类里面包含的方法,从其元数据里面可以看到,如下:

    Code
     
     
    标签: C#HttpRuntimeAsp.Net
  • 相关阅读:
    mysql5.6 sql_mode设置为宽松模式
    utf-8 编码问题
    阿里云服务器挂载云盘
    maven打包含有多个main程序的jar包及运行方式
    AndroidStudio OpenCv的配置,不用安装opencv manager
    图片标注工具LabelImg使用教程
    关于tensorboard启动问题
    IntelliJ IDEA 最新激活码(截止到2018年10月14日)
    JetBrains C++ IDE CLion配置与评测
    Win10下Clion配置opencv3
  • 原文地址:https://www.cnblogs.com/x-poior/p/6487177.html
Copyright © 2011-2022 走看看