【轉】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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM