asp.net第二天 iis內部機制與一般處理程序

http://www.cnblogs.com/wupeiqi/archive/2013/03/10/2952214.html


http://blog.csdn.net/sundacheng1989/article/details/9995263

通信處理過程:

當服務器運行正常的情況下,客戶端(瀏覽器)
向服務器端發送請求時,服務器端負責監聽的套接字(socket),監聽到有連接請求後,會爲該客戶端建立一個用於通信的套接字與客戶端進行通信。當用戶在瀏覽器向服務器發送請求時,瀏覽器會按照雙方都約定好的網絡傳輸層http協議,將請求轉換成符合Http協議的請求報文。然後通過設備按照TCP協議發送到服務器。在服務器端接收到請求報文後。會按照Http協議對報文進行解析。若請求的內容爲靜態的數據,服務器端直接將被請求的數據,按照Http協議生成響應報文後返回給瀏覽器。瀏覽器然後解析收到的報文。將頁面顯示到瀏覽器窗口。(注:最開始僅是顯示一個html 框架。經過多次請求。將CSS樣式,圖片………逐一的加載進來形成一個完整的頁面。這個過程,有多次的交互通信。當通信結束後會把用來通信的套接字銷燬,因爲http協議是一種無狀態的通信。這樣減輕了服務器的壓力)

當瀏覽器向客戶端發送的請求爲動態的。那麼服務器(IIS)發現處理不了這種後綴名的文件時,會通過映射表到。響應實現了接口的可擴展程序asp.net_isapi.dll, 然後asp.net_isapi.dll,又將請求轉交給網站程序處理.網站程序調用

httpRuntime類的processRequest方法來處理:

1.此類會分析接收到的請求報文.將請求報文封裝到名稱爲httpWorkerRequest的類的屬性中(便於其它地方以用).

2.創建HttpContext對象.這個對象是當前所請求報文的上下文環境.它包含了所有的請求數據.其中有兩個最重要類的對象:http.Request和http.Response.  在httpRequest對象中又包含了兩個屬性.Form(通過表單請求的數據參數).Querystring(通過URL傳遞的數據參數); 通過索引器,可以找到參數的值. 在httpResponse 對象中有一個TextWriter對象.在它裏面保存的是被請求的頁面在執行過程中要向瀏覽器輸出的數據.可以通過write 方法對其進行輸出給瀏覽器。

3.通過HttpApplicationFactory類的的一個靜態方法。來爲每個請求創建一個單獨的httpApplication對象。在創建之前HttpApplicationFactor會到HttpApplication池中查看,有沒有空閒的。若有直接用。沒有的時候才創建新的HttpApplication。

4.在httpApplication裏運行己轉換成接口IhttpHandler 的通過反射被請求頁面對象的ProcessRequest 方法.

方法執行過程如下先執行httpApplication中的processRequest方法。在此方法中包含了要按照先後順序執行的19個委託事件 當在執行到第8個事件的時候就開始創建被請求頁面對象,在執行到第11和第12個事件之間時。就執行被創建的請求頁面對象的ProcessRequest方法。

 

 

(二)開始頁面生命週期

1.頁面生命週期的主要階段包括: 階段 事件/方法   
頁面初始化          Page_Init  
加載View State      LoadViewState   
回發數據處理      LoadPostData   
頁面加載          Page_Load   
回發通知          RaisePostDataChangedEvent  
回發事件處理     RaisePostBackEvent  
頁面預渲染       Page_PreRender   
保存             viewstate SaveViewState   
Page渲染         Page_Render   
Page 卸載       Page_UnLoad  

2.頁面生命週期的主要事件:

PreInit:

1.檢查IsPostBack 屬性

2.動態設置Master Page

3.動態設置Theme

4.設置控件的默認值(UniqueId等)

5.重新創建動態控件(初始化控件),初始化控件的值

Init: 這個事件發生在所有的控件被初始化,所有的皮膚設置被應用以後。它用來讀取或者初始化控件屬性。它能夠用來註冊一些aspx頁面中沒有指出的控件的事件。

InitComplete: Use this event for processing tasks that require all initialization to be complete.

PreLoad: 加載頁面的ViewState和所有的控件,然後處理所有的包含在Request實例中的postback數據。

Load: 這個事件可能是大家最熟悉的了。需要注意的是,Page對象會遞歸的調用子控件的onload事件直到頁面和所有的子控件被加載完成。這個事件主要用來設置控件屬性的值,建立數據庫連接(通常不這麼做)。

Validation: 如果你的控件要求驗證,驗證會在這個階段發生,這個時候你可以檢查控件的IsValid屬性。跟這個階段關聯的事件是Validate,它有一個可以接受驗證字符串羣的重載方法(overload method),這個重載方法執行特定控件羣的驗證。

Control events: 這個就不多說了,主要是處理控件的事件,例如click。這也就讓我們明白了每次我們click一個Button的時候,實際上是要先去執行load事件然後才執行click事件的,一般我們用!IsPostBack來判斷一下從而避免執行不必要的加載邏輯。

LoadComplete: 頁面所有的控件都被加載以後執行,暫時沒有想到用來幹什麼。。。

PreRender: 在HTML被生成之前這是最後一個事件。每一個頁面中的控件都有PreRender的過程。在這裏對將要輸出的HTML結果進行最後一次修改。

SaveStateComplete: 在這個時間發生之前,已經保存了所有控件和頁面的,任何對page或者控件的改動都不會產生左右。暫時沒想到用來幹啥。

Render: 它不是一個事件而是一個方法。工作就是把HTML寫回客戶端瀏覽器。

UnLoad: 頁面中的每一個控件都會發生這件事。在控件中,使用這個事件來做清理工作,例如關閉數據庫連接等。對與頁面本身也是做清理工作,例如關閉打開的文件和數據庫連接,或者結束日誌或者其它指定的工作。

需要說明的是,每次Request都會創建一個全新的Page類的實例,所以在頁面中的自己定義的字段是不能在兩次request中傳遞值的,需要使用viewstate來存儲。

頁面處理的整體過程圖解

 ----------------------------------------------此圖可以直觀的看出執行過程----------------------------------------

 

 

 

更詳細的過程可以從陽陽多在博客中發表的用三張圖片詳解Asp.Net 全生命週期 一文中詳讀

下面我們使用三張圖片解析ASP.net的整個生命週期,我總感覺使用圖片更加的清楚的說明這種問題,所以使用的這樣方式

 

說明:

1  第一張圖片從全局說明從客戶端發出一個Request請求,服務器windows內核中的HTTP.SYS組件接收該請求開始到IIS處理完該請求並響應到客戶端結束。

2  第二張圖片爲圖1中Http處理管線的詳細步驟

3  第三張圖片爲圖2Http處理管線中調用處理程序(HttpHandler,  此處爲Page對象)的詳細生命週期過程。

 

 

圖1:


 

 

 

圖2:  Http處理管線詳解


 

圖3:  Asp.Net生命週期詳解


 


一:iis機制原理

1.瀏覽器將請求封裝成Socket發送到iis

2.iis分爲內核模式和用戶模式

2.1.內核模式 HTTP.SYS 的內置驅動程序來監聽來自外部的 HTTP請求。在操作系統啓動的時候,IIS首先在HTTP.SYS中註冊自己的虛擬路徑

2.2..用戶模式有httpadmin

http的請求和響應過程-----管道

以IIS 6.0爲例,在工作進程w3wp.exe中,利用aspnet_isapi.dll加載.NET運行時(如果.NET運行時尚未加載),IIS 6.0引入了應用程序池的概念,一個工作進程對應着一個應用程序池。一個應用程序池可以承載一個或多個Web應用,每個Web應用映射到一個IIS虛擬目錄。與IIS 5.x一樣,每一個Web應用運行在各自的應用程序域中。

如果HTTP.SYS接收到的HTTP請求是對該Web應用的第一次訪問,在成功加載了運行時後,會通過AppDomainFactory爲該Web應用創建一個應用程序域,隨後一個特殊的運行時IsapiRuntime被加載。IsapiRuntime定義在程序集System.Web中,對應的命名空間爲System.Web.Hosting,被加載的IsapiRuntime會接管該HTTP請求。

IsapiRuntime會首先創建一個IsapiWorkerRequest對象,用於封裝當前的HTTP請求,並將該IsapiWorkerRequest對象傳遞給ASP.NET運行時HttpRuntime。從此時起,HTTP請求正式進入了ASP.NET管道。HttpRuntime會根據IsapiWorkerRequest對象創建用於表示當前HTTP請求的上下文(Context)對象HttpContext。

隨着HttpContext被成功創建,HttpRuntime會利用HttpApplicationFactory創建新的或獲取現有的HttpApplication對象。實際上ASP.NET維護着一個HttpApplication對象池,HttpApplicationFactory從池中選取可用的HttpApplication用於處理HTTP請求,處理完畢後將其釋放到對象池中。HttpApplicationFactory負責處理當前的HTTP請求。

在HttpApplication初始化過程中,會根據配置文件加載並初始化相應的HttpModule對象。對於HttpApplication來說,在它處理HTTP請求的不同階段會觸發不同的事件(Event),而HttpModule的意義在於通過註冊HttpApplication的相應的事件,將所需的操作注入整個HTTP請求的處理流程。ASP.NET的很多功能,比如身份驗證、授權、緩存等,都是通過相應的HttpModule實現的。

最終完成對HTTP請求的處理實現在HttpHandler中。對於不同的資源類型,具有不同的HttpHandler。比如.aspx頁面對應的HttpHandler爲System.Web.UI.Page,WCF的.svc文件對應的HttpHandler爲System.ServiceModel.Activation.HttpHandler。上面整個處理流程如圖1-11所示。


 

HttpApplication

HttpApplication是整個ASP.NET基礎架構的核心,它負責處理分發給它的HTTP請求。由於一個HttpApplication對象在某個時刻只能處理一個請求,只有完成對某個請求的處理後,HttpApplication才能用於後續的請求的處理,所以ASP.NET採用對象池的機制來創建或獲取HttpApplication對象。

當第一個請求抵達時,ASP.NET會一次創建多個HttpApplication對象,並將其置於池中,選擇其中一個對象來處理該請求。處理完畢後,HttpApplication不會被回收,而是釋放到池中。對於後續的請求,空閒的HttpApplication對象會從池中取出,如果池中所有的HttpApplication對象都處於繁忙的狀態,ASP.NET會創建新的HttpApplication對象。

HttpApplication處理請求的整個生命週期是一個相對複雜的過程,在該過程的不同階段會觸發相應的事件。我們可以註冊相應的事件,將處理邏輯注入到HttpApplication處理請求的某個階段。表1-1按照實現的先後順序列出了HttpApplication在處理每一個請求時觸發的事件名稱。

表1-1  HttpApplication事件列表

 

名    稱 描    述
BeginRequest HTTP管道開始處理請求時,會觸發BeginRequest事件
AuthenticateRequest,PostAuthenticateRequest ASP.NET先後觸發這兩個事件,使安全模塊對請求進行身份驗證
AuthorizeRequest,PostAuthorizeRequest ASP.NET先後觸發這兩個事件,使安全模塊對請求進程授權
ResolveRequestCache,PostResolveRequestCache ASP.NET先後觸發這兩個事件,以使緩存模塊利用緩存的內容對請求直接進行響應(緩存模塊可以將響應內容進行緩存,對於後續的請求,直接將緩存的內容返回,從而提高響應能力)
PostMapRequestHandler 對於訪問不同的資源類型,ASP.NET具有不同的HttpHandler對其進行處理。對於每個請求,ASP.NET會通過擴展名選擇匹配相應的HttpHandler類型,成功匹配後,該實現被觸發
AcquireRequestState,PostAcquireRequestState ASP.NET先後觸發這兩個事件,使狀態管理模塊獲取基於當前請求相應的狀態,如SessionState
PreRequestHandlerExecute,PostRequestHandlerExecute ASP.NET最終通過與請求資源類型相對應的HttpHandler實現對請求的處理,在實行HttpHandler前後,這兩個實現被先後觸發
ReleaseRequestState,PostReleaseRequestState ASP.NET先後觸發這兩個事件,使狀態管理模塊釋放基於當前請求相應的狀態
UpdateRequestCache,PostUpdateRequestCache ASP.NET先後觸發這兩個事件,以使緩存模塊將HttpHandler處理請求得到的內容得以保存到輸出緩存中
LogRequest,PostLogRequest ASP.NET先後觸發這兩個事件爲當前請求進行日誌記錄
EndRequest 整個請求處理完成後,EndRequest事件被觸發

對於一個ASP.NET應用來說,HttpApplication派生於Global.asax文件,我們可以通過創建global.asax文件對HttpApplication的請求處理行爲進行定製。Global.asax採用一種很直接的方式實現了這樣的功能,這種方式不是我們常用的方法重寫或事件註冊,而是直接採用方法名匹配。在Global.asax中,我們按照“Application_{Event Name}”這樣的方法命名規則進行事件註冊。比如Application_BeginRequest方法用於處理HttpApplication的BeginRequest事件。如果通過VS創建一個Global.asax文件,將採用如下的默認定義。
<%@ Application Language="C#" %>
<script runat="server">
    void Application_Start(object sender, EventArgs e){}   
    void Application_End(object sender, EventArgs e){}       
    void Application_Error(object sender, EventArgs e){}
    void Session_Start(object sender, EventArgs e){}
    void Session_End(object sender, EventArgs e){}
</script>
HttpModule

ASP.NET擁有一個具有高度可擴展性的引擎,並且能夠處理對於不同資源類型的請求,那麼是什麼成就了ASP.NET的高可擴展性呢? HttpModule功不可沒。

當請求轉入ASP.NET管道時,最終負責處理該請求的是與請求資源類型相匹配的HttpHandler對象,但是在Handler正式工作之前,ASP.NET會先加載並初始化所有配置的HttpModule對象。HttpModule在初始化的過程中,會將一些功能註冊到HttpApplication相應的事件中,在HttpApplication請求處理生命週期中的某個階段,相應的事件會被觸發,通過HttpModule註冊的事件處理程序也得以執行。

所有的HttpModule都實現了具有如下定義的System.Web.IHttpModule接口,其中Init方法用於實現HttpModule自身的初始化,該方法接受一個HttpApplication對象,有了這個對象,事件註冊就很容易了。
public interface IHttpModule
{
    void Dispose();
    void Init(HttpApplication context);
}

ASP.NET提供的很多基礎功能都是通過相應的HttpModule實現的,下面列出了一些典型的HttpModule。

OutputCacheModule:實現了輸出緩存(Output Caching)的功能。

SessionStateModule:在無狀態的HTTP協議上實現了基於會話(Session)的狀態。

WindowsAuthenticationModule+FormsAuthenticationModule+PassportAuthentication Module:實現了Windows、Forms和Passport這3種典型的身份認證方式。

UrlAuthorizationModule + FileAuthorizationModule:實現了基於URI和文件ACL(Access Control List)的授權。

除了這些系統定義的HttpModule之外,我們還可以自定義HttpModule,通過Web.config可以很容易地將其註冊到Web應用中。

HttpHandler

對於不同資源類型的請求,ASP.NET會加載不同的Handler來處理,也就是說.aspx 頁面與.asmx web 服務對應的Handler是不同的。所有的HttpHandler都實現了具有如下定義的接口System.Web.IHttpHandler,方法ProcessRequest提供了處理請求的實現。
public interface IHttpHandler
{  
    void ProcessRequest(HttpContext context);
    bool IsReusable { get; }
}

某些HttpHandler具有一個與之相關的HttpHandlerFactory,它實現了具有如下定義的接口System.Web.IHttpHandlerFactory,方法GetHandler用於創建新的HttpHandler,或者獲取已經存在的HttpHandler。
public interface IHttpHandlerFactory
{
    IHttpHandler GetHandler(HttpContext context, string requestType,
      string url, string pathTranslated);
    void ReleaseHandler(IHttpHandler handler);
}

HttpHandler和HttpHandlerFactory的類型都可以通過相同的方式配置到Web.config中。下面一段配置包含對.aspx、.asmx和.svc這3種典型的資源類型的HttpHandler配置。
<configuration>
  <system.web>
    <httpHandlers>
      <add path="*.svc"
            verb="*"
            type="System.ServiceModel.Activation.HttpHandler,
                    System.ServiceModel, Version=4.0.0.0, Culture=neutral,
                    PublicKeyToken=b77a5c561934e089"
            validate="false"/>
      <add path="*.aspx"
            verb="*"
            type="System.Web.UI.PageHandlerFactory"
            validate="true"/>
      <add path="*.asmx"
            verb="*"
            type="System.Web.Services.Protocols.WebServiceHandlerFactory,
                    System.Web.Services, Version=4.0.0.0, Culture=neutral,
                    PublicKeyToken=b03f5f7f11d50a3a"
            validate="False"/>
    </httpHandlers>
  </system.web>
</configuration>


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章