国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > .NET > 正文

ASP.NET 中 Session 實現(xiàn)原理淺析 [1] 會話的建立流程

2024-07-10 12:56:21
字體:
供稿:網(wǎng)友


http 協(xié)議之所以能夠獲得如此大的成功,其設(shè)計實現(xiàn)的簡潔性和無狀態(tài)連接的高效率是很重要的原因。而為了在無狀態(tài)的 http 請求和有狀態(tài)的客戶端操作之間達(dá)到平衡,產(chǎn)生了服務(wù)器端會話 (session) 的概念。客戶端在連接到服務(wù)器后,就由 web 服務(wù)器產(chǎn)生并維護(hù)一個客戶端的會話;當(dāng)客戶端通過無狀態(tài) http 協(xié)議再次連接到服務(wù)器時,服務(wù)器根據(jù)客戶端提交的某種憑據(jù),如 cookie 或 url 參數(shù),將客戶關(guān)聯(lián)到某個會話上。這種思路在各種開發(fā)語言和開發(fā)環(huán)境中大量得到應(yīng)用。
在 asp.net 中,web 應(yīng)用程序和會話狀態(tài)被分別進(jìn)行維護(hù),通過 httpapplication 和 httpsessionstate 分離 web 應(yīng)用程序與會話的功能。應(yīng)用程序?qū)舆壿嬙?global.asax 文件中實現(xiàn),運行時編譯成 system.web.httpapplication 的實例;會話則作為單獨的 system.web.sessionstate.httpsessionstate 實例,由服務(wù)器統(tǒng)一為每個用戶會話維護(hù),通過 asp.net 頁面編譯成的 system.web.ui.page 對象子類的 session 屬性訪問。關(guān)于 asp.net 中不同層次關(guān)系可參考我以前的一篇文章《.net 1.1中預(yù)編譯asp.net頁面實現(xiàn)原理淺析 [1] 自動預(yù)編譯機制淺析》,以下簡稱【文1】。

asp.net 在處理客戶端請求時,首先將根據(jù)客戶端環(huán)境,生成一個 system.web.httpcontext 對象,并將此對象作為執(zhí)行上下文傳遞給后面的頁面執(zhí)行代碼。
在【文1】的分析中我們可以看到,httpruntime 在處理頁面請求之前,根據(jù) httpworkerrequest 中給出的環(huán)境,構(gòu)造 httpcontext 對象,并以次對象作為參數(shù)從應(yīng)用程序池中獲取可用應(yīng)用程序。簡要代碼如下:
以下內(nèi)容為程序代碼:

private void httpruntime.processrequestinternal(httpworkerrequest wr)
{
// 構(gòu)造 http 調(diào)用上下文對象
httpcontext ctxt = new httpcontext(wr, 0);

//...

// 獲取當(dāng)前 web 應(yīng)用程序?qū)嵗?
ihttphandler handler = httpapplicationfactory.getapplicationinstance(ctxt);

// 調(diào)用 handler 實際處理頁面請求
}




httpapplicationfactory 工廠內(nèi)部維護(hù)了一個可用的應(yīng)用程序?qū)嵗彌_池,用戶降低應(yīng)用程序?qū)ο髽?gòu)造的負(fù)荷。
如果池中沒有可用的應(yīng)用程序?qū)ο髮嵗藢ο蠊S最終會調(diào)用 system.web.httpruntime.createnonpublicinstance 方法構(gòu)造新的應(yīng)用程序?qū)嵗⒄{(diào)用其 initinternal 方法初始化。詳細(xì)步驟分析見【文1】
以下內(nèi)容為程序代碼:

internal static ihttphandler httpapplicationfactory.getapplicationinstance(httpcontext ctxt)
{
// 處理定制應(yīng)用程序
//...

// 處理調(diào)試請求
//...

// 判斷是否需要初始化當(dāng)前 httpapplicationfactory 實例
//...

// 獲取 web 應(yīng)用程序?qū)嵗?
return httpapplicationfactory._theapplicationfactory.getnormalapplicationinstance(ctxt);
}

private httpapplication httpapplicationfactory.getnormalapplicationinstance(httpcontext context)
{
httpapplication app = null;

// 嘗試從已施放的 web 應(yīng)用程序?qū)嵗犃兄蝎@取
//...

if(app == null)
{
// 構(gòu)造新的 web 應(yīng)用程序?qū)嵗?
app = (httpapplication)system.web.httpruntime.createnonpublicinstance(this._theapplicationtype);

// 初始化 web 應(yīng)用程序?qū)嵗?
app.initinternal(context, this._state, this._eventhandlermethods);
}

return app;
}



這里的 system.web.httpapplication.initinternal 函數(shù)完成對應(yīng)用程序?qū)ο蟮某跏蓟ぷ鳎ㄕ{(diào)用 httpapplication.initmodules 函數(shù)初始化 http 模塊(后面將詳細(xì)介紹),并將作為參數(shù)傳入的 httpcontext 實例保存到 httpapplication._context 字段中。而此 http 上下文對象將被后面用于獲取會話對象。
以下內(nèi)容為程序代碼:

public class httpapplication : ...
{
private httpcontext _context;
private httpsessionstate _session;

public httpsessionstate session
{
get
{
httpsessionstate state = null;
if (this._session != null)
{
state = this._session;
}
else if (this._context != null)
{
state = this._context.session;
}
if (state == null)
{
throw new httpexception(httpruntime.formatresourcestring("session_not_available"[img]/images/wink.gif[/img]);
}
return state;
}
}
}



而在 asp.net 頁面中獲取會話的方法也是類似,都是通過 httpcontext 來完成的。
以下內(nèi)容為程序代碼:

public class page : ...
{
private httpsessionstate _session;
private bool _sessionretrieved;

public virtual httpsessionstate session
{
get
{
if (!this._sessionretrieved)
{
this._sessionretrieved = true;
try
{
this._session = this.context.session;
}
catch (exception)
{
}
}
if (this._session == null)
{
throw new httpexception(httpruntime.formatresourcestring("session_not_enabled"[img]/images/wink.gif[/img]);
}
return this._session;
}
}
}



在 httpcontext 中,實際上是通過一個哈希表保存諸如會話對象之類信息的
以下內(nèi)容為程序代碼:

public sealed class httpcontext : ...
{
private hashtable _items;

public idictionary items
{
get
{
if (this._items == null)
{
this._items = new hashtable();
}
return this._items;
}
}

public httpsessionstate session
{
get
{
return ((httpsessionstate) this.items["aspsession"]);
}
}
}



而 httpcontext.session 所訪問的又是哪兒來的呢?這就又需要回到我們前面提及的 httpapplication.initmodules 函數(shù)。

在 .net 安裝目錄 config 子目錄下的 machine.config 定義了全局性的配置信息,而 httpapplication 就是使用其中 system.web 一節(jié)的配置信息進(jìn)行初始化的。
以下內(nèi)容為程序代碼:

<system.web>
<httpmodules>
<add name="outputcache" type="system.web.caching.outputcachemodule" />
<add name="session" type="system.web.sessionstate.sessionstatemodule" />
<add name="windowsauthentication" type="system.web.security.windowsauthenticationmodule" />
<add name="formsauthentication" type="system.web.security.formsauthenticationmodule" />
<add name="passportauthentication" type="system.web.security.passportauthenticationmodule" />
<add name="urlauthorization" type="system.web.security.urlauthorizationmodule" />
<add name="fileauthorization" type="system.web.security.fileauthorizationmodule" />
<add name="errorhandlermodule" type="system.web.mobile.errorhandlermodule, system.web.mobile, version=1.0.5000.0, culture=neutral, publickeytoken=b03f5f7f11d50a3a" />
</httpmodules>
</system.web>



httpmodules 節(jié)點指定了 httpapplication 需要初始化的模塊列表,而在前面提到的 httpapplication.initmodules 函數(shù)正式根據(jù)此列表進(jìn)行初始化的
以下內(nèi)容為程序代碼:

private void httpapplication.initmodules()
{
httpmodulesconfiguration cfgmodules = ((httpmodulesconfiguration) httpcontext.getappconfig("system.web/httpmodules"[img]/images/wink.gif[/img]);

if (cfgmodules == null)
{
throw new httpexception(httpruntime.formatresourcestring("missing_modules_config"[img]/images/wink.gif[/img]);
}
_modulecollection = cfgmodules.createmodules();

for(int i = 0; i < _modulecollection.count; i++)
{
_modulecollection[i].init(this);
}

globalizationconfig cfgglobal = ((globalizationconfig) httpcontext.getappconfig("system.web/globalization"[img]/images/wink.gif[/img]);
if (cfgglobal != null)
{
_applevelculture = cfgglobal.culture;
_appleveluiculture = cfgglobal.uiculture;
}
}



session 節(jié)點對于的 system.web.sessionstate.sessionstatemodule 對象將被 httpmodulesconfiguration.createmodules 方法構(gòu)造,并調(diào)用其 init 函數(shù)初始化。sessionstatemodule 類實際上就是負(fù)責(zé)管理并創(chuàng)建會話,用戶完全可以自行創(chuàng)建一個實現(xiàn) ihttpmodule 接口的類,實現(xiàn)會話的控制,如實現(xiàn)支持集群的狀態(tài)同步等等。
sessionstatemodule.init 方法主要負(fù)責(zé) machine.config 文件中的 sessionstate 配置,調(diào)用 sessionstatemodule.initmodulefromconfig 方法建立相應(yīng)的會話管理器。
以下內(nèi)容為程序代碼:

<system.web>
<sessionstate mode="inproc"
stateconnectionstring="tcpip=127.0.0.1:42424"
statenetworktimeout="10"
sqlconnectionstring="data source=127.0.0.1;integrated security=sspi"
cookieless="false"
timeout="20" />
</system.web>



sessionstate 的使用方法請參加 msdn 中相關(guān)介紹和 info: asp.net state management overview。關(guān)于不同 mode 的會話管理的話題我們后面再討論,先繼續(xù)來看會話的建立過程。

在從 machine.config 文件中讀取配置信息后,initmodulefromconfig 方法會向 httpapplication 實例注冊幾個會話管理事件處理函數(shù),負(fù)責(zé)在應(yīng)用程序合適的情況下維護(hù)會話狀態(tài)。
以下內(nèi)容為程序代碼:

private void sessionstatemodule.initmodulefromconfig(httpapplication app,
sessionstatesectionhandler.config config, bool configinit)
{
// 處理不使用 cookie 的情況
//...

app.addonacquirerequeststateasync(new begineventhandler(this.beginacquirestate),
new endeventhandler(this.endacquirestate));
app.releaserequeststate += new eventhandler(this.onreleasestate);
app.endrequest += new eventhandler(this.onendrequest);

// 創(chuàng)建會話管理器
//...
}



beginacquirestate 和 endacquirestate 作為一個異步處理器注冊到 httpapplication._acquirerequeststateeventhandlerasync 字段上;onreleasestate 則負(fù)責(zé)在合適的時候清理會話狀態(tài);onendrequest 則是 onreleasestate 的一個包裝,負(fù)責(zé)較為復(fù)雜的請求結(jié)束處理。前面提到的 httpapplication.initinternal 函數(shù),在完成了初始化工作后,會將上述這些事件處理器,加入到一個執(zhí)行隊列中,由應(yīng)用程序在合適的時候,使用流水線機制進(jìn)行調(diào)用,最大化處理效率。有關(guān) asp.net 中流水線事件模型的相關(guān)介紹,請參考 http pipelines
securely implement request processing, filtering, and content redirection with http pipelines in asp.net 一文中 the pipeline event model 小節(jié),有機會我在寫文章詳細(xì)分析。

知道了會話建立的調(diào)用流程再來看會話的實現(xiàn)就比較簡單了,sessionstatemodule.beginacquirestate 被 httpapplication 實例在合適的時候調(diào)用,處理各種會話的復(fù)雜情況后,使用 sessionstatemodule.completeacquirestate 函數(shù)完成實際的會話建立工作,并將封裝會話的 httpsessionstate 對象以 "aspsession" 為 key 加入到 httpcontext 的哈希表中,也就是前面提到的 httpcontext.context 的由來。而 sessionstatemodule.onreleasestate 則從 httpcontext 中刪除 "aspsession" 為 key 的 httpsessionstate 對象,并對會話管理器進(jìn)行同步工作。

至此,asp.net 中的會話建立流程大概就分析完畢了,下一小節(jié)將進(jìn)一步展開分析多種不同會話管理器的實現(xiàn)原理與應(yīng)用。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 甘孜县| 吉林市| 普陀区| 彰化县| 巴里| 五峰| 钦州市| 新民市| 湄潭县| 高陵县| 河东区| 南开区| 惠来县| 祁门县| 赤峰市| 边坝县| 凤翔县| 怀安县| 祁阳县| 中西区| 邵武市| 城固县| 山阴县| 三门峡市| 吉木萨尔县| 平和县| 比如县| 华亭县| 凤山市| 湟中县| 玛曲县| 平阴县| 潜江市| 望奎县| 嘉义市| 萍乡市| 霍城县| 辽阳市| 涡阳县| 睢宁县| 丰原市|