ASP.NET运行机制原理01
---浏览器与IIS的交互过程
一、浏览器和服务器的交互原理
(一)、浏览器和服务器交互的简单描述:
1.通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去访问一台电脑上访问文件一样,只不过浏览器的访问请求是由被访问的电脑上的一个 WEB服务器软件来接收处理,它会分析接收到的请求信息,从而按照请求信息来找到服务器电脑上的文件,经过处理,最终将生成的内容发回到浏览器。
简单的说就是:由浏览器生成一条“命令”,通过互联网发给另一台电脑的某个软件(服务器软件);服务器软件接收到“命令”,就分析理解这个“命令”,然后按照“命令”找到服务器电脑上的文件,将文件内容发送回浏览器。
2.通过上图,我们看到了浏览器和服务器交互的简单过程。现在,我们要想想,浏览器和服务器软件到底是神马东东,他们之间又是如何交互信息的呢?
其实,浏览器和服务器软件,就是两个独立的应用程序(就如qq、office、画图工具一样)。那么两个应用程序之间要交互信息,就牵扯到了应用程序通信的问题。那他俩是使用神马方式通信的呢?
答案是套接字:Socket。至于Socket的具体用法和原理,篇幅问题不在此文中写了,先预留位置在这,下次补上《基于多线程和套接字的简易WebServer软件-没有控件的ASP.NET》。
浏览器和服务器软件通过套接字来发送和接收对方的信息,但现在的关键问题是,他们发送和接收的到底是什么?--- 基于Http协议的报文数据(详见《Http协议介绍---没有控件的ASP.NET》)。
也就是说:浏览器和服务器软件其实就是两个使用Socket进行通信的的两个应用程序:双方都发送按照 Http协议语法规范组织的数据,接收到数据后都按照 Http协议语法规范来解释。
(二)、浏览器和IIS(or other webserver)交互机制
上图就是IIS (服务器软件)
1.浏览器和IIS交互过程:
我们都知道,在互联网上确定一台电脑的位置是使用IP寻址,但为什么当我们平时访问网站时直接输入一个域名也能够访问到某个服务器电脑进而由对方的服务器软件发送响应页面数据给我呢?下面我把简单步骤列出:
(1)在浏览器输入网址: www.oumind.com/index.html,浏览器按照Http协议语法生成请求报文数据。
(2).浏览器检查本机是否保存了 www.oumind.com/index.html. 域名对应的服务器IP地址。如果没有,则发送请求到所在城市网中最近的DNS服务器(域名解析服务器),它会根据我们发送来的域名查询到该域名对应的服务器IP地址,并发送回浏览器。
(3)浏览器从DNS服务器获得了 www.oumind.com/index.html域名对应的服务器电脑IP,则将请求报文通过Socket发送到服务器电脑。(注意:Http协议规定服务器软件使用的默认端口是80,通俗的说,就是如果浏览器访问一个网站页面,浏览器默认就是将请求报文发送到服务器80端口,而服务器负责监听这个端口的软件一般就是服务器软件—比如asp.net用的IIS,java用的Tomcat。)
(4)IIS接收到请求报文,分析请求报文,从中获取请求的页面路径 /index.html。判断页面的后缀名,如果是静态页面(.html/.jpg/.css/.js等),则直接由IIS软件的组件读取该文件内容,并将内容通过Socket发送回浏览器。
(5)但如果此时请求的是一个动态页面(.aspx/.ashx),IIS自己就处理不了 (因为IIS软件开发出来的时候,ASP.NET程序还不存在呢) 。所以,IIS就去它的扩展程序映射表中根据被请求文件后缀名查看是否有能够处理这种文件的扩展程序。
而我们ASPNET中常用的文件 .aspx/.ashx等对应的处理程序是 aspnet_isapi.dll。如下图:
(6)如果IIS根据后缀名找到对应的处理程序,则通过调用此程序来处理浏览器发送来的请求报文。
至于,之后又进行了什么操作,请继续关注:
《ASP.NET运行机制原理02_ASP.NET整体运行机制01从浏览器到HttpApplication ---没有控件的ASP.NET》
ASP.NET运行机制原理02
---ASP.NET整体运行机制01
--从浏览器到HttpApplication
一、ASP.NET整体运行机制
(一)、浏览器和服务器交互的简单描述:
1.通俗描述:当针对服务器动态页面的请求被由IIS通过扩展程序aspnet_isapi.dll交给ASP.NET后,ASP.NET机制并不是如之前我们自己编写的那个简易WebServer软件那样直接反射被请求页面类对象,而是打造了一个完整而复杂的处理过程,其中就包含了著名的“ASP.NET请求处理管道”和“页面生命周期”。
2.下面我们来通过分析反编译的ASP.NET源码来详细的介绍,这个过程:
(1).IIS处理如何将请求信息通过aspnet_isapi.dll 这个扩展程序传给 ASP.NET的呢?
IIS接到一个针对动态页面(.aspx)的请求,自己处理不了,就调用aspnet_isapi.dll这个服务器扩展程序,再有aspnet_isapi.dll将请求交给ASP.NET,也就是一个名为aspnet_wp.exe的工作进程(篇幅原因,此文不在此介绍Domain了)。aspnet_wp.exe就调用FrameWork里的类 ------- ISAPIRuntime。
(2).我们来看看ISAPIRuntime的类:
public sealed class ISAPIRuntime : MarshalByRefObject, IISAPIRuntime, IRegisteredObject
分析:
a.继承了MarshalByRefObject:从而以此获得跨应用程序访问对象的能力。
b.实现了 IISAPIRuntime接口,让我们来看看这个接口里一个最重要的方法:
[return: MarshalAs(UnmanagedType.I4)]
int ProcessRequest([In] IntPtr ecb, [In, MarshalAs(UnmanagedType.I4)] int useProcessModel);
注意看第一个参数:IntPtr ecb,是一个指针对象,其实就是保存的aspnet_isapi.dll的引用,为什么要位ProcessRequest方法传入这个指针?因为ASP.NET需要通过这个指针对应的aspnet_isapi.dll对象从IIS处获得浏览器发来的请求报文,并且当ASP.NET最后处理完页面生成响应报文后,也要通过它将响应报文发回给IIS再有IIS发回到浏览器。
c.继承MarshalByRefObject的原因也就是为了能访问到托管代码外的这个aspnet_isapi.dll。
(3).在ISAPIRuntime中调用了实现了接口IISAPIRuntime 的方法ProcessRequest。此方法中做了两重大的事情:
a.创建WorkerRequest对象:通过调用CreateWorkerRequest (IntPtr ecb, bool useOOP)方法来创建一个ISAPIWorkerRequest对象,此对象中包含了请求报文,并拥有和aspnet_isapi.dll通讯的能力。
b. 调用HttpRuntime.ProcessRequestNoDemand(HttpWorkerRequest wr)方法,然后在此方法里通过调用HttpRuntime实例方法ProcessRequestInternal(HttpWorkerRequest wr),开始处理请求。
(4).HttpRuntime中调用的ProcessRequestInternal(HttpWorkerRequest wr)做了3个重要的事情:
a.生成上下文对象(HttpContext),为上下文对象context内部的两个重要的成员赋值:Reqeust和Response,前者负责向ASP.NET和程序员提供请求报文的数据,后者向ASP.NET和程序员提供储存要输出到浏览器的数据的地方。
(I).内部的HttpRequest对象:根据wr里封装的报文数据进一步封装出了HttpRequest对象。
(II).内部的HttpResponse对象:在内部初始化了一个HtmlWriter对象,用来保存服务端要输出给浏览器的页面代码。
(III).注意,如果在创建context时出现错误,比如浏览器发来的请求报文格式错误,那么就会直接在此时向浏览器输出400响应报文。
b.创建HttpApplication handler,此对象中执行请求的动态页面对象创建和执行的整个过程。
(I).通过HttpApplicationFactory创建-HttpApplicationFactory.GetApplicationInstance(context);
注意此方法中为创建的HttpApplication对象传入了上下文对象context。
(II).HttpApplication具体执行过程请见下文。
c.当HttpApplication执行完后,调用FinishRequest方法,生成并输出响应报文到浏览器。
那么,HttpApplication具体执行过程到底如何呢?请继续后天继续关注:
《ASP.NET运行机制原理03_ASP.NET整体运行机制02辛苦的HttpApplication ---没有控件的ASP.NET》