对IIS只有表面的理解 现在模拟一下IIS的内部原理:
[C#] 纯文本查看 复制代码
public int ServerScoket { get; set; }
private void btnStart_Click(object sender, EventArgs e)
{
IPAddress ipAddress = IPAddress.Parse(this.txtIP.Text);
IPEndPoint endpoint = new IPEndPoint(ipAddress, int.Parse(this.txtPort.Text));
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socket.Bind(endpoint);
socket.Listen(10);
this.lbStatus.Text = "启动";
this.lbStatus.ForeColor = Color.Green;
//开始socket的接受请求
ThreadPool.QueueUserWorkItem(a =>
{
//线程池默认都是后台线程
Socket serverSocket = (Socket)a;
while (true)
{
//获取到跟浏览器交互的代理socket
var proxSocket= serverSocket.Accept();
ThreadPool.QueueUserWorkItem(s =>
{
Socket pSocket = (Socket)s;
byte[] bytes = new byte[1024 * 1024];
int realLength = pSocket.Receive(bytes);
//把当前的报文封装到了strRequest里面去了
string strRequest = Encoding.UTF8.GetString(bytes, 0, realLength);
//处理当前的报文,解析当前报文,看看请求是哪个文件,
//把请求的文件封装成相应的报文,通过socket发送给浏览器
ProcessRequest(strRequest, pSocket);
}, proxSocket);
}
},socket);
}
//处理客户端的请求
private void ProcessRequest(string strRequest, Socket pSocket)
{
//把请求行取出来
//初始化请求信息和响应信息实例
HttpContext context = new HttpContext(strRequest);
HttpApplication application = new HttpApplication();
//这时候,请求的响应已经做好了
//正在处理HTTP请求
application.ProcessRequest(context);
//context response
pSocket.Send(context.Response.GetHeader());
pSocket.Send(context.Response.BodyData);
pSocket.Shutdown(SocketShutdown.Both);
pSocket.Close();
}
HttpContext封装上下文
[C#] 纯文本查看 复制代码 public class HttpContext
{
//设置请求
public HttpRequest Request { get; set; }
//响应的实例
public HttpResponse Response { get; set; }
//构造函数
public HttpContext(string httpRequestStr)
{
Request = new HttpRequest(httpRequestStr);
Response = new HttpResponse(Request);
}
}
HttpRequest对象
[C#] 纯文本查看 复制代码 /// <summary>
/// 封装请求报文的信息
/// </summary>
public class HttpRequest
{
/*
GET /login.aspx HTTP/1.1
Accept: text/html, application/xhtml+xml, #1#*
Accept-Language: zh-CN
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; QDesk 2.3.1185.202; Windows NT 6.1; Trident/5.0)
Accept-Encoding: gzip, deflate
Host: localhost:38888
Connection: Keep-Alive*/
//将报文传进来
public HttpRequest(string requestStr)
{
if(!string.IsNullOrEmpty(requestStr))
{
string[] lines=requestStr.Replace("\r\n","\r").Split('\r');
//处理请求的Method
this.Method = lines[0].Split(' ')[0];
//设置请求的URL 地址
this.RequestURL = lines[0].Split(' ')[1];
}
}
//是Get 还是set
public string Method { get; set; }
public string RequestURL { get; set; }
}
HttpResponse
[C#] 纯文本查看 复制代码 View Code
public class HttpResponse
{
//请求文件的后缀
private string _requestFileExt;
public HttpResponse(HttpRequest request)
{
_requestFileExt = Path.GetExtension(request.RequestURL);
}
//获取相应提报文字节数组
public byte[] BodyData { get; set; }
//获取响应头部
public byte[] GetHeader()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("HTTP/1.1 200 OK\r\n");
sb.AppendFormat("Content-Type: {0} \r\n", GetContentType(_requestFileExt));
return Encoding.UTF8.GetBytes(sb.ToString());
}
public string GetContentType(string _requestFileExt)
{
string type = "text/html";
switch (_requestFileExt)
{
case ".aspx":
case ".html":
case ".htm":
type = "text/html";
break;
case ".png":
type = "image/png";
break;
case ".gif":
type = "image/gif";
break;
case ".jpg":
case ".jpeg":
type = "image/jpeg";
break;
case ".css":
type = "text/css";
break;
case ".js":
type = "application/x-javascript";
break;
default:
type = "text/plain";
break;
}
return type;
}
//返回响应主体
public byte[] GetBodyData()
{
return BodyData;
}
}
HttpApplication 中处理
[C#] 纯文本查看 复制代码 public class HttpApplication
{ public void ProcessRequest(HttpContext context)
{
string ext = Path.GetExtension(context.Request.RequestURL);
switch (ext)
{
case ".jpg":
case ".jpeg":
case ".html":
case ".htm":
case ".css":
case ".js":
ProcessStaticFile(context); break;
case ".aspx":
ProcessDynamicFile(context);
break;
default:
ProcessStaticFile(context);
break;
}
}
//处理动态页面
public void ProcessDynamicFile(HttpContext context)
{
//假设请求Index.aspx
string className=Path.GetFileNameWithoutExtension(context.Request.RequestURL);
//获取命名空间
string nameSpace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;
//_02HeimaIIS.IndexPage
string fullName = nameSpace + "." + className;
//用接口接受不同的实例
IHttpHandler obj=(IHttpHandler)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(fullName,true);
if (obj == null)
{
}
else
{
obj.ProcessRequest(context);
}
}
//处理静态页面
public void ProcessStaticFile(HttpContext context)
{
string currentWebDir = AppDomain.CurrentDomain.BaseDirectory;
string fileName=Path.Combine(currentWebDir,context.Request.RequestURL.TrimStart('/'));
context.Response.BodyData = File.ReadAllBytes(fileName);
}
}
如果是静态网页直接返回
如果是动态页面通过反射实现
以上就是面向接口编程
[C#] 纯文本查看 复制代码 public class MyPage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
//可以访问数据库,就是动态的
string strBody = @"<html><head></head><body><h2> big shit y</h2></body></html>";
context.Response.BodyData = Encoding.UTF8.GetBytes(strBody);
}
}
IIS内部处理的文字总结:
设置一个监听队列,用一个应用程序池中的实例socket A,接受浏览器发送的数据,再从应用程序池中获取一个实例 socket B将接受到的数据进行处理,而 socket A 不断接受浏览器的请求。
socket B处理数据(用到HttpContext HttpApplication MyPage IHandler)
HttpContext
HttpRequest 获取请求的方法 及请求的地址
HttpResponse得到响应体和 响应头
HttpApplication
根据后缀名判断是动态网页还是静态网页
动态网页:通过反射获取命名空间 通过请求地址找到类名 通过反射获取实例转化成接口,调用其方法。
处理完成后,由代理socket发送报文头和报文体
|