<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>简单生活 —— Kevin Yang的博客 &#187; 应用程序域</title> <atom:link href="http://www.imkevinyang.com/tags/%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9f%9f/feed" rel="self" type="application/rss+xml" /><link>http://www.imkevinyang.com</link> <description>It&#039;s all about sharing</description> <lastBuildDate>Mon, 06 Sep 2010 08:00:00 +0000</lastBuildDate> <generator>http://wordpress.org/?v=2.9.1</generator> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <item><title>（转）Http 请求处理流程</title><link>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html</link> <comments>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html#comments</comments> <pubDate>Mon, 20 Jul 2009 15:24:00 +0000</pubDate> <dc:creator>Kevin Yang</dc:creator> <category><![CDATA[好文分享]]></category> <category><![CDATA[AspDotNet]]></category> <category><![CDATA[HTTP请求]]></category> <category><![CDATA[原理]]></category> <category><![CDATA[应用程序域]]></category><guid isPermaLink="false">http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html</guid> <description><![CDATA[<p class="quote"><font color="#ff8040">文章来自：</font><a href="http://www.tracefact.net/Asp-Net-Architecture/Http-Request-Processing-Flow.aspx" target="_blank">张子阳</a></p><h2>引言</h2><p>我查阅过不少Asp.Net的书籍，发现大多数作者都是站在一个比较高的层次上讲解Asp.Net。他们耐心、细致地告诉你如何一步步拖放控件、设置控件属性、编写CodeBehind代码，以实现某个特定的功能。</p><p>这种做法，实际上是回答了<strong>&#34;如何去做&#34;</strong>的问题，却没有回答<strong>&#34;为什么可以这样做&#34;</strong>的问题。</p><p>尽管我很推崇 悉江华 先生的《圣殿祭祀的Asp.Net开发详解》一书，但当我翻看了一下其对角色(Ro&#8230;</p>]]></description> <content:encoded><![CDATA[</p><p class="quote"><font color="#ff8040">文章来自：</font><a href="http://www.tracefact.net/Asp-Net-Architecture/Http-Request-Processing-Flow.aspx" target="_blank">张子阳</a></p><h2>引言</h2><p>我查阅过不少Asp.Net的书籍，发现大多数作者都是站在一个比较高的层次上讲解Asp.Net。他们耐心、细致地告诉你如何一步步拖放控件、设置控件属性、编写CodeBehind代码，以实现某个特定的功能。</p><p>这种做法，实际上是回答了<strong>&quot;如何去做&quot;</strong>的问题，却没有回答<strong>&quot;为什么可以这样做&quot;</strong>的问题。</p><p>尽管我很推崇 悉江华 先生的《圣殿祭祀的Asp.Net开发详解》一书，但当我翻看了一下其对角色(Role) 和 用户(Member)的讲解时，我决定跳过去直接读后面的章节。因为我发现他也随了大流，对这部分的讲解停留在&quot;如何去做&quot;的层面上。我相信像悉先生 这样的牛人是不可能不了解底层运作原理的，仅仅是因为那本书原本就已经很厚了吧。</p><p>当你按&quot;如何去做&quot;所讲解的内容去开发程序的时候，对于你的用户，你仍是一名程序员；但对于实现了MembershipProvider 和 RoleProvider 抽象类的微软开发人员来说，你已经成了他们的一个用户。</p><p><strong>NOTE：</strong>我既不反对一些作者只讲解&quot;如何去做&quot;，也不反对你只学&quot;如何去做&quot;，这样也有它的好处，就是可以快速开发。我只是建议多掌握一点底层知识，对一些问题会有更好的理解。</p><p>希望通过这一系列文章的讲解，可以让你更好的理解Asp.Net的运作原理和做以了解。</p><h2>Http请求处理流程概述</h2><p>思考&quot;为什么在地址栏输入www.tracefact.net就可以看到张子阳的个人空间？&quot;，类似于思考&quot;为什么苹果是往地上掉不是往天上 飘？&quot;。对于普通访问者来说，这就像每天太阳东边升起西边落下一样是理所当然的；对于很多程序员来说，认为这个与己无关，不过是系统管理员或者网管员的责 任。毕竟，IIS是 Windows 的一个组件，又不是 Asp.Net 的一个组成部分。而实际上，从你轻拍回车到页面呈现在你眼前的十分之一秒内，IIS和.Net Framework已经做了大量的幕后工作。</p><p>你可能觉得了解这些幕后工作是如何运作的无关紧要，作为程序员的你只要保证开发出的程序可以高效地运行就可以了。然而，在开发过程中，你却发现常常 需要使用诸如 HttpContext 这样的类。这个时候，你可曾思考过这些类的构成和类的实体是如何创建的？你可能简单地回答：HttpContext代表当前请求的一个上下文环境。可你又 知道IIS 、Framework、Asp.Net 是如何协同工作处理每个Http请求、如何区分不同的请求、IIS、Framework、Asp.Net三者之间的数据如何流动么？</p><p>回答上面这些问题，首先需要了解IIS是如何处理页面请求的，这也是理解 Form验证模式和Windows 验证模式 的基础。</p><h2>Http请求刚刚到达服务器的时候</h2><p>当服务器接收到一个 Http请求的时候，IIS 首先需要决定如何去处理这个请求（<strong>NOTE：</strong>服务器处理一个.htm页面和一个.aspx页面肯定是不一样的么）。那IIS依据什么去处理呢？―― 根据文件的后缀名。</p><p>服务器获取所请求的页面（<strong>NOTE：</strong>也可以是文件，比如 jimmy.jpg）的后缀名以后，接下来会在服务器端寻找可以处理这类后缀名的应用程序，如果IIS找不到可以处理此类文件的应用程序，并且这个文件也没有受到服务器端的保护（<strong>NOTE：</strong>一个受保护的例子就是 App_Code中的文件，一个不受保护的例子就是你的js脚本），那么IIS将直接把这个文件返还给客户端。</p><p>能够处理各种后缀名的应用程序，通常被称为 ISAPI 应用程序（<strong>NOTE：</strong>Internet Server Application Programe Interface，互联网服务器应用程序接口）。虽然这 ISAPI 听上去还挺气派，也算是&quot;应用程序&quot;呢，但仔细看看它的全称就明白了：<strong></strong><strong><font color="#008000"><strong>它实际上只是一个接口，起到一个代理的作用，它的主要工作是映射所请求的页面(文件) 和与此后缀名相对应的实际的处理程序。</strong></font></strong></p><p>让我们更进一步地看一下 ISAPI ，看看它到底是什么样子，请按下面的步骤进行：</p><ol><li>打开IIS。</li><li>选择随意一个站点，鼠标右键，&quot;属性&quot;。</li><li>选择&quot;主目录&quot;选项卡。</li><li>选择&quot;配置&quot;。</li></ol><p>你应该会看到如下的画面：</p><p>图1. 应用程序配置</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image001.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="应用程序配置" border="0" alt="应用程序配置" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image001_thumb.gif" width="465" height="515" /></a></p><p>很清楚地就可以看到，所有IIS所能处理，或者叫 ISAPI 所提供代理服务的 文件类型 及其相对应的实际的后台处理程序都在这里清楚地列出来了。</p><p>我们找到 .aspx 的应用处理程序，然后点&quot;编辑&quot;，会出现下面的画面：</p><p>图2. 编辑.aspx文件的处理程序</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image002.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="编辑.aspx文件的处理程序" border="0" alt="编辑.aspx文件的处理程序" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image002_thumb.gif" width="515" height="295" /></a></p><p>一路看到这里，可以看出，所有的.aspx文件实际上都是由 aspnet_isapi.dll 这个程序来处理的，当IIS把对于.aspx页面的请求提交给了aspnet_isapi.dll以后，它就不再关心这个请求随后是如何处理的了。现在我们应该知道：Asp.Net 只是服务器(IIS)的一个组成部分而已，它是一个 ISAPI扩展。</p><p>这里需要注意两点：</p><ul><li>当你修改&quot;限制为&quot;后，可以限制页面(文件)只能以某种特定方式访问</li><li>&quot;确认文件是否存在&quot;是实现 URL 地址映射的关键选项，我以后会专门讲述。</li></ul><h2>理解宿主环境（Hosting）</h2><p>从本质上讲，Asp.Net 主要是由一系列的类组成，这些类的主要目的就是将Http请求转变为对客户端的响应。HttpRuntime类是Asp.Net的一个主要入口，它有一个称作ProcessRequest 的方法，这个方法以一个 HttpWorkerRequest 类作为参数。HttpRuntime 类几乎包含着关于单个Http请求的所有信息：所请求的文件、服务器端变量、QueryString、Http 头信息 等等。Asp.Net 使用这些信息来加载、运行正确的文件，并且将这个请求转换到输出流中，一般来说，也就是HTML页面。</p><p><strong>NOTE：</strong>二般来说，也可以是张图片。</p><p>当 Web.config文件的内容发生改变 或者 .aspx文件发生变动的时候，为了能够卸载运行在同一个进程中的应用程序（<strong>NOTE：</strong>卸载也是为了重新加载），Http请求被分放在相互隔离的应用程序域中。</p><p><strong>NOTE：</strong>可能你以前就听过应用程序域，但是不了解怎么回事，应用程序域就是 AppDomain。</p><p>对于IIS来说，它依赖一个叫做 HTTP.SYS 的内置驱动程序来监听来自外部的 HTTP请求。在操作系统启动的时候，IIS首先在HTTP.SYS中注册自己的虚拟路径。</p><p><strong>NOTE：</strong>实际上相当于告诉HTTP.SYS哪些URL是可以访问的，哪些是不可以访问的。举个简单的例子：为什么你访问不存在的文件会出现 404 错误呢？就是在这一步确定的。</p><p>如果请求的是一个可访问的URL，HTTP.SYS会将这个请求交给 IIS 工作者进程。</p><p><strong>NOTE：</strong>IIS6.0中叫做 w3wp.exe，IIS5.0中叫做 aspnet_wp.exe。</p><p>每个工作者进程都有一个身份标识 以及 一系列的可选性能参数。</p><p><strong>NOTE：</strong>可选性能参数，是指诸如 回收机制的设置、超时时间设置 等等。</p><p><strong>接下来进行的事情就是上一章节讲述的 ISAPI 了。</strong></p><p><strong>NOTE：</strong>这部分的内容相关性比较强，为了让大家好理解，我最后还是决定把 ISAPI 放到前面了，可能全系列完成的时候会再调整吧。</p><p>除了映射文件与其对应的处理程序以外，ISAPI 还需要做一些其他的工作：</p><ol><li>从HTTP.SYS中获取当前的Httq请求信息，并且将这些信息保存到 HttpWorkerRequest 类中。</li><li>在相互隔离的应用程序域AppDomain中加载HttpRuntime。</li><li>调用 HttpRuntime的ProcessRequest方法。</li></ol><p>接下来才是程序员通常编写的代码所完成的工作了，然后，IIS 接收返回的数据流，并重新返还给 HTTP.SYS，最后，HTTP.SYS 再将这些数据返回给客户端浏览器。</p><p>OK，现在你看到张子阳的空间主页了。</p><p>图3.Asp.Net 的宿主环境</p><p><a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image0018.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Asp.Net 的宿主环境" border="0" alt="Asp.Net 的宿主环境" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image0018_thumb.gif" width="465" height="352" /></a></p><h2>理解管道（Pipeline）</h2><p>在前面两章中，我们在一个相对比较低的层次上讨论了从发出Http请求到看到浏览器输出这转瞬即逝的十分之一秒内IIS和 Framework 所做的事情。但是我们忽略了一个细节：程序员编写的代码是如何在这一过程中衔接的，本章我们就来看看这个问题。</p><p>当Http请求进入 Asp.Net Runtime以后，它的管道由托管模块（NOTE：Managed Modules）和处理程序（NOTE：Handlers）组成，并且由管道来处理这个 Http请求。<a href="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image00110.gif"><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="来自宿主环境的HTTP请求" border="0" alt="来自宿主环境的HTTP请求" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/clip_image00110_thumb.gif" width="515" height="373" /></a></p><p>我们按编号来看一下这幅图中的数据是如何流动的。</p><p>1. HttpRuntime将Http请求转交给 HttpApplication，HttpApplication代表着程序员创建的Web应用程序。HttpApplication创建针对此Http 请求的 HttpContext对象，这些对象包含了关于此请求的诸多其他对象，主要是HttpRequest、HttpResponse、 HttpSessionState等。这些对象在程序中可以通过Page类或者Context类进行访问。、</p><p>2. 接下来Http请求通过一系列Module，这些Module对Http请求具有完全的控制权。<strong></strong><strong><font color="#008000"><strong>这些Module可以做一些执行某个实际工作前的事情</strong>。</font></strong></p><p>3. Http请求经过所有的Module之后，它会被HttpHandler处理。在这一步，执行实际的一些操作，通常也就是.aspx页面所完成的业务逻 辑。可能你会觉得在创建.aspx页面并没有体会到这一过程，但是，你一定知道，.aspx 页面继承自Page类，我们看一下Page类的签名：</p><p>public class Page : TemplateControl, IHttpHandler{ <br />// 代码省略 <br />}</p><p>可以看到，Page类实现了IHttpHandler接口，HttpHandler也是Http请求处理的最底层。</p><p>4.HttpHandler处理完以后，Http请求再一次回到Module，<strong>此时Module可以做一些某个工作已经完成了之后的事情。</strong></p><p><strong>NOTE：</strong>注意我用红色标识的字，然后回想一下：Asp.Net 中是不是有众多的 Inserting 、Inserted 之类成对的事件？其实，这里讲述的就是为什么Asp.Net可以将一个Insert操作分成前后两部分，然后再分别进行事件拦截的幕后原理。</p><p>如果我们将注意力只集中在Http请求、HttpHandler和HttpModule上，不去考虑HttpContext和HttpApplication，那么图4.可以简化成下面这样：</p><p><strong>图5.Http请求在HttpHandler 和 HttpModule 中的流动方向</strong></p><p><img style="border-right-width: 0px; margin: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Http请求在HttpHandler 和 HttpModule 中的流动方向" border="0" alt="Http请求在HttpHandler 和 HttpModule 中的流动方向" src="http://www.imkevinyang.com/wp-content/uploads/2009/07/image_thumb.png" width="219" height="296" /></p><h2>总结</h2><p>本文中，我首先概要介绍了这系列文章将要为大家讲述的主题。然后，我提出了部分程序员存在的一个问题：在一个比较高的层次上学习和使用Asp.Net。</p><p>随后，我以一个访问我个人空间首页的例子，引出了本文主要讲述的三个内容：</p><ol><li>Http请求刚刚到达时IIS时，IIS 所做的工作。</li><li>Http请求的宿主环境。</li><li>Http管道。</li></ol><p>希望这篇文章能给你带来帮助。</p>标签：<a href="http://www.imkevinyang.com/tags/aspdotnet" title="AspDotNet" rel="tag">AspDotNet</a>, <a href="http://www.imkevinyang.com/tags/http%e8%af%b7%e6%b1%82" title="HTTP请求" rel="tag">HTTP请求</a>, <a href="http://www.imkevinyang.com/tags/%e5%8e%9f%e7%90%86" title="原理" rel="tag">原理</a>, <a href="http://www.imkevinyang.com/categories/greatpoststoshare" title="好文分享" rel="tag">好文分享</a>, <a href="http://www.imkevinyang.com/tags/%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e5%9f%9f" title="应用程序域" rel="tag">应用程序域</a><br /><h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4><ul class="st-related-posts"><li><a href="http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html" title="Asp.Net页面的编码问题 (2009/11/27)">Asp.Net页面的编码问题</a> (2009/11/27)</li></ul>]]></content:encoded> <wfw:commentRss>http://www.imkevinyang.com/2009/07/%ef%bc%88%e8%bd%ac%ef%bc%89http-%e8%af%b7%e6%b1%82%e5%a4%84%e7%90%86%e6%b5%81%e7%a8%8b.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> </channel> </rss>