在写这篇博客之前,知好多前辈已经写过,自己班门弄斧,主要是加深自己对细节的理解,另一方面希望对浏览此篇文章的读者一个新的认识。注定是一长篇。肯定有新的认识,图示都是原创。
此篇所有牵涉的细节,我会一一列出,估计持续更新数日。
当从浏览器发送到服务器一个请求,整个流程与细节的把握。IIS5和IIS6的有些许的不同。
全面理解,把握细节:
一,请求到达IIS再到Framework。若看以下的讲解,需要了解:
1,IIS5和IIS6都具备inetinfo.exe进程。
2, inetinfo.exe(任务管理器看到)的作用:包括许多由IIS提供的服务(HTTP、FTP、SMTP等)。Inetinfo.exe接收来自TCP/IP子系统的请求,并将这些请求送往各自的服务, 这些服务又解释请求,执行请求,并把结果返回给客户机。因为所有这些服务都在同一个进程 (inetinfo.exe) 中运行,所以它们能够共享高速缓存的数据,如文件句柄、 帐户信息和日志文件数据。
3,Name Pipes命名管道是一种协议,相当于TCP/IP中的Socket协议,两者有很大的相似之处,用到局域网和广域网的各自优点。
详情请参照:http://msdn.microsoft.com/zh-cn/library/ms187892.aspx
4,inetinfo.exe和aspnet_isapi.dll的关系,这里之处为”调用“是否有不妥之处。也就是了解.exe文件和.dll文件的之间的关系,此点自己查阅相关资料。
5,注册表:在这里的主要作用为文件的关联。详情自己查阅相关资料。
6,Work Process工作者进程在IIS5和IIS6分别叫做w3wp.exe和aspnet_wp.exe。两者指得都是工作者进程,只是名字不同。
7,IIS(非托管)和FrameWork(托管)之间的通信:IIS是非托管程序,而FrameWork上是托管程序,两者通过指针ecb将Request传递资源包。
8,托管和非托管代码代码。请参考:http://www.cnblogs.com/Holmes-Jin/archive/2012/03/14/2396411.html
9,http.sys在(C:\Windows\System32\drivers\)中,内核模式与用户模式,属于操作系统的知识,这里不做深入研究。
一,IIS5由inetinfo.exe接受来自浏览器的请求,然后调用”aspnet_isapi.dll“,aspnet_isapi.dll"遵照"”命名管道协议Named Pipes“通过ecb指针(非托管的资源包)和Work Process(w3wp.exe)进行传输,此时aspnet_isapi.dll与w3wp.exe属于不同的进程,传输效率不是最优的,在iis6中优化了这一点。
二,IIS6是服务器的网卡驱动内核模块C:\Windows\System32\drivers\http.sys监听到,然后会查询注册表Regitry此请求和那个应用程序关联(注册表的用途之一)处理。交予W3SVC服务(属于svchost.exe进程中的一个服务,能在任务管理器“服务“中看到,)然后查看inetinfo.exe交予aspnet_isapi.dll,此时的aspnet_isapi.dll被划进Worker Process工作者进程中(aspnet_wp.exe),交予FrameWork处理。因为aspnet_wp.exe与FrameWork属于同一工作者进程,传输效率大大优于IIS5。IIS6,它是完全为ASP.NET做过优化的。
是的,我也做个图。
二,请求到达进入framework后所做的处理。
对所请求的文件的文件扩展名进行检查,确定应由哪个 ISAPI 扩展处理该请求,然后将该请求传递给合适的 ISAPI 扩展。ASP.NET 处理已映射到其上的文件扩展名,如 .aspx、.ascx、.ashx 和 .asmx
1,先创建“appdomain”,应用程序域。隔离作用。有关应用程序域的作用:请参考http://www.cnblogs.com/leslies2/archive/2012/03/06/2379235.html
由System.Web.Hosting.ApplicationManager类,此类有公开的方法和未公开的方法,大多和客户端和服务端的应用程序域有关系。详情:http://msdn.microsoft.com/zh-cn/system.web.hosting.applicationmanager.aspx
2,创建“hostingenvironment”,宿主环境。
由System.Web.Hosting.HostingEnviroment类实例化一个对象创建。详情参考:http://msdn.microsoft.com/zh-cn/library/vstudio/System.Web.Hosting.HostingEnvironment(v=vs.100).aspx
3,创建核心对象,ISAPIRuntime、HttpRuntime,HttpWorkRequest、HttpContext、HttpRequest、HttpResponse和和HttpApplicationFactory、HttpApplication。实现IHttpHandler
此过程最为复杂,自己理解,
第一,由aspnet_isapi.dll调用System.Web.Hosting.ISAPIRuntime类中的ProcessRequest方法。此类有2个重要作用。读者可以用反编译工具查询这个类。
作用:1,接受IntPtr类型的指针变量ecb创建System.Web.HttpWorkRequest类wr对象。大多数情况下,代码不会直接处理 HttpWorkerRequest,这是因为请求和响应数据是通过HttpRequest和 HttpResponse 类公开的。
作用:2,调用HttpRuntime类的public static void ProcessRequest(HttpWorkerRequest wr)调用ProcessRequestNoDemand(wr);方法继续调用ProcessRequestNow(wr);方法继续调用theRuntime.ProcessRequestInternal(wr);方法创建HttpContext 有context = new HttpContext(wr, false);。读者也可以用反编译工具查询这个类。
第二,创建HttpApplicationFactory对象,将context创建并传值到Application对象。在创建之前HttpApplicationFactory会到HttpApplication池中查看,有没有空闲的。若有直接用。没有的时候才创建新的HttpApplication。读者也可以用反编译工具查询这个类。
第三,HttpRuntime类创建Context的时候同样具有另外一个作用,调用HttpApplicationFactory就是创建Appplication对象,IHttpHandler applicationInstance = HttpApplicationFactory.GetApplicationInstance(context);继续调用theApplicationFactory.GetNormalApplicationInstance(context);
有关HttpApplication。是作用整个程序运行期间(用于数据共享)。
HttpRquerst(URL传来的Querystring和提交的表单form数据)。
HttpResponse(有一个TextWriter对象,存储想浏览器发送的数据。)
有关TextWriter和Render方法,以下简介:有关到页面生命周期。下面会有讲述。
1,
System.IO.TextWriter有个子类叫做System.Web.UI.HtmlTextWriter 用reflector可以看到public class HtmlTextWriter : TextWriter
根据MSDN的描述,HtmlTextWriter类用于将标记字符和文本写入到ASP.NET服务器控件输出流。此类提供了ASP.NET服务器控件在向客户端呈现标记时所使用的格式设置功能。
HtmlTextWriter是一个储存html代码的类。示例:http://blog.itpub.net/14466241/viewspace-573265/
2,
①但是上面的向“客户端呈现”是另一个类的功能,Render方法。此方法有好多类都具有,“呈现“。多为虚方法,让其自定义子类实现多态。比如ControlAdapter用于改写控件的html代码的一个类。
在处理的这个阶段,Page 对象会在每个控件上调用此方法。所有 ASP.NET Web 服务器控件都有一个用于写出发送给浏览器的控件标记的 Render 方法。
创建自定义控件的时候,通常要覆盖此方法以输出控件的标记。不过,如果自定义控件只合并标准的 ASP.NET Web 服务器控件,不合并自定义标记,则不需要覆盖 Render方法。示例:http://www.cnblogs.com/tonyqus/archive/2005/02/15/104576.html
public abstract class ControlAdapter {
protected internal virtual void Render(HtmlTextWriter writer);
}
②当然render方法也存在System.Web.UI.Control中,也是虚方法。
protected internal virtual void Render(HtmlTextWriter writer) { this.RenderChildren(writer); } |
public class HttpApplication : IComponent, IDisposable, IHttpAsyncHandler, IHttpHandler, IRequestCompletedNotifier, ISyncContext
**IhttpHangdler 里的pr方法,被Web.UI.Page与HttpApplication继承。就是将“上下文”返回到浏览器。
**IhttpModule:当一个过滤器Filter(自定义一个类),1,继承此接口2,实现此接口中的init(Application context)方法 ,3并在config文件配置
Global文件就是继承了Application类,就是一个过滤器,简化了自定义过滤器的步骤(省去config配置等麻烦),工作中就用这种形式,想做其他的事件 只需Application_事件名字就OK.
Application 本身具有一些事件 start end 等。一旦程序运行,就是种存在,共享。
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
}
protected void Session_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
}
protected void Application_Error(object sender, EventArgs e)
{
}
protected void Session_End(object sender, EventArgs e)
{
}
protected void Application_End(object sender, EventArgs e)
{
}
了解这两个接口:同样意义很大。
①public interface IHttpHandler
{
// Methods
void ProcessRequest(HttpContext context);
// Properties
bool IsReusable { get; }
}
②public interface IHttpModule { // Methods void Dispose(); void Init(HttpApplication context); } |
4,由HttpApplication管道处理请求。
下面是请求管道中的19个事件.
(1)BeginRequest: 开始处理请求
(2)AuthenticateRequest授权验证请求,获取用户授权信息
(3):PostAuthenticateRequest获取成功
(4):AunthorizeRequest 授权,一般来检查用户是否获得权限
(5):PostAuthorizeRequest:获得授权
(6):ResolveRequestCache:获取页面缓存结果
(7):PostResolveRequestCache 已获取缓存
(8):PostMapRequestHandler 创建页面对象:aspx创建了页面对象,控件树。ashx创建最终处理当前http请求的 Handler 实例: 第一从HttpContext中获取当前的PR Handler ,Create
获取当前的上下文(HttpContext)已经映射了PrHandler没?是:结束。空的话:创建PrHandler对象实例
(9):PostAcquireRequestState 获取Session
(10)PostAcquireRequestState 获得Session
(11)PreRequestHandlerExecute:准备执行页面对象
**中间调用页面对象继承Page类(继承IhttpHangdler类 )的子类页面对象的ProcessRequest方法,(在Application里转换成接口IhttpHandler 的通过反射被请求页面对象的ProcessRequest 方法).
(12)PostRequestHandlerExecute 执行完页面对象了
(13)ReleaseRequestState 释放请求状态
(14)PostReleaseRequestState 已释放请求状态
(15)UpdateRequestCache 更新缓存
(16)PostUpdateRequestCache 已更新缓存
(17)LogRequest 日志记录
(18)PostLogRequest 已完成日志
(19)EndRequest 完成
对的我需要来个图。
4,在Application的第8个事件创建处理对象的时候,这里就以aspx为例子。执行页面的生命周期。流程是这样的。
首先随便vs建一个应用程序,添加一个web窗体,后置代码反射出其对应的DLL,然后用Reflector反编译查看此页面的执行的周期。
得到的
此页面,先建立控件树。然后执行页面的PR方法,进一步调用。
此图,是别人所做,我找不到这人的博客了。只有图被摘下。在此特别注释。