当前位置: 首页 > 图文教程 > 网络编程 > ASP.NET > CASSINI源代码分析(4)

ASP.NET
如何使用vb6.0来实现中文实名搜索
C#实现Window管道技术
记录下一些关于测试工具NUNIT的链接资料,有兴趣的朋友也可以跳过去看看
编写与.NET属性窗口交互的RAD组件(自序)
asp.net 关于form认证的一般设置:
编写与.NET属性窗口交互的RAD组件(一)
ActiveX控件的打包发布[无证书发布](一)
Visual SourceSafe 6.0 的问题思考
VB报表输出的问题,恳请不吝赐教
证书和签名--试用微软提供的证书测试工具系列
[dotNET]如何利用ConfigurationSettings.AppSettings.GetValues读取配置文件中多个...
使用C#编写DES加密程序的framework
令你的网页速度大大提高
怎样得到一个系统盘的全名,不是字符,是全名,如:本地磁盘(C:)?
r在richtextbox中插入动画/控件
Code: Writing Text to a File (Visual Basic)
算法讨论:哲学家就餐问题
我们所要关注的是什么?
firebird 连接嵌入式版本
从Csharp走到VB.Net(一):MyClass保留字

ASP.NET 中的 CASSINI源代码分析(4)


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-03   浏览: 78 ::
收藏到网摘: n/a

因为connection对象仅仅跟host对象相关,且处理一个套接字,所以其数据成员仅有:private Host _host; //指向宿主对象 private Socket _socket; //当前套接字我们知道host调用且仅了conn.ProcessOneRequest();方法,所以我们首先要找到此方法(coneetion很多方法,我们先看看主要的):public void ProcessOneRequest() { // wait for at least some input if (WaitForRequestBytes() == 0) { WriteErrorAndClose(400); return; } Request request = new Request(_host, this); request.Process(); }从代码来看,此过程首先要确保socket有数据读入,如果发生无法读取,就向socket写入一个400错误;如果有数据读入,那么构造一个requese对象,调用request的Process方法(呵呵,麻烦事大家总是一层层甩给别人J)。还是继续分析Connection对象, WaitForRequestBytes()实际上是单独线程来读取socket,如果socket连接但是没有数据流,就至多等待10秒。WriteErrorAndClose(int);函数调用WriteErrorAndClose(int , string){ String body = Messages.FormatErrorMessageBody(statusCode, _host.VirtualPath); if (message != null && message.Length > 0) body += "\r\n"; WriteEntireResponseFromString(statusCode, null, body, false);}WriteEntireResponseFromString()函数根据状态码构造返回的http数据流,并写回到客户端。实际上体现了对http协议的具体实现。我们暂时放下,追踪看看Request对象。internal class Request : SimpleWorkerRequest {。。。。。。}继承自.net,根据MSDN介绍:HttpWorkerRequest 的这种简单实现提供请求 URL 和查询字符串,并将输出的正文捕获到 TextWriter 中。若要实现更为丰富的功能(如提供已发送的内容和标头以及捕获以二进制数据表示的响应标头或响应正文),则应扩展 SimpleWorkerRequest 并重写适当的 HttpWorkerRequest 方法。还是从Process函数入手看看(代码较长):{ReadAllHeaders(); //阅读处所有的http请求头 if (_headerBytes == null || _endHeadersOffset < 0 || _headerByteStrings == null || _headerByteStrings.Count == 0) { _conn.WriteErrorAndClose(400); return; //如果读取http头错误就返回 } ParseRequestLine(); //处理request行输入 // Check for bad path if (IsBadPath()) { //防止用户请求bad路径 _conn.WriteErrorAndClose(400); return; } // Limit to local requests only if (!_conn.IsLocal) { _conn.WriteErrorAndClose(403); return; } // Check if the path is not well formed or is not for the current app bool isClientScriptPath = false; String clientScript = null; if (!_host.IsVirtualPathInApp(_path, out isClientScriptPath, out clientScript)) { _conn.WriteErrorAndClose(404); //检验url请求是否属于应用程序路径范围内,如果不是,报404错误。 return; } ParseHeaders(); //解析http请求头 ParsePostedContent(); //解析post方法的内容 if (_verb == "POST" && _contentLength > 0 && _preloadedContentLength < _contentLength) { //如果是post方法,需要等待post数据完成才继续那么调用conn的等待方法Write100Continue直到post完成 _conn.Write100Continue(); } // special case for client script if (isClientScriptPath) { //如果请求的是脚本路径,那么直接读取文件(也就是.js文件,按照文本文件来看待) _conn.WriteEntireResponseFromFile(_host.PhysicalClientScriptPath + clientScript, false); return; } // special case for directory listing if (ProcessDirectoryListingRequest()) { //如果是请求目录list,则处理后返回 return; } PrepareResponse(); //准备响应内容 // Hand the processing over to HttpRuntime HttpRuntime.ProcessRequest(this); //通过HttpRuntime的方法执行asp.net的内容,驱动所有 ASP.NET Web 处理执行。} 针对该函数细节,逐个分析以下函数: ReadAllHeaders ParseRequestLine ParsePostedContent ProcessDirectoryListingRequest PrepareResponse 因为他们处理一次http request。 private void ReadAllHeaders() { _headerBytes = null; do { if (!TryReadAllHeaders()) break; // something bad happened } while (_endHeadersOffset < 0); // found \r\n\r\n } 该函数不断调用TryReadAllHeaders,仔细看看这个TryReadAllHeaders: private bool TryReadAllHeaders() { // read the first packet (up to 32K) byte[] headerBytes = _conn.ReadRequestBytes(maxHeaderBytes); //从connection读取最大数据32*1024字节。 if (headerBytes == null || headerBytes.Length == 0) return false; //如果读取数据失败,返回错误,调用此函数者应当检查数据读取是否完整 if (_headerBytes != null) { // previous partial read 以下将当前读取的数据累加 in