对IIS只有表面的理解 现在模拟一下IIS的内部原理:

1 public int ServerScoket { get; set; } 2 private void btnStart_Click(object sender, EventArgs e) 3 { 4 IPAddress ipAddress = IPAddress.Parse(this.txtIP.Text); 5 IPEndPoint endpoint = new IPEndPoint(ipAddress, int.Parse(this.txtPort.Text)); 6 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 7 socket.Bind(endpoint); 8 socket.Listen(10); 9 this.lbStatus.Text = "启动"; 10 this.lbStatus.ForeColor = Color.Green; 11 //开始socket的接受请求 12 ThreadPool.QueueUserWorkItem(a => 13 { 14 //线程池默认都是后台线程 15 Socket serverSocket = (Socket)a; 16 while (true) 17 { 18 //获取到跟浏览器交互的代理socket 19 var proxSocket= serverSocket.Accept(); 20 21 ThreadPool.QueueUserWorkItem(s => 22 { 23 Socket pSocket = (Socket)s; 24 byte[] bytes = new byte[1024 * 1024]; 25 int realLength = pSocket.Receive(bytes); 26 //把当前的报文封装到了strRequest里面去了 27 string strRequest = Encoding.UTF8.GetString(bytes, 0, realLength); 28 //处理当前的报文,解析当前报文,看看请求是哪个文件, 29 //把请求的文件封装成相应的报文,通过socket发送给浏览器 30 ProcessRequest(strRequest, pSocket); 31 }, proxSocket); 32 } 33 },socket); 34 } 35 //处理客户端的请求 36 private void ProcessRequest(string strRequest, Socket pSocket) 37 { 38 //把请求行取出来 39 //初始化请求信息和响应信息实例 40 HttpContext context = new HttpContext(strRequest); 41 HttpApplication application = new HttpApplication(); 42 43 //这时候,请求的响应已经做好了 44 //正在处理HTTP请求 45 application.ProcessRequest(context); 46 47 //context response 48 pSocket.Send(context.Response.GetHeader()); 49 pSocket.Send(context.Response.BodyData); 50 pSocket.Shutdown(SocketShutdown.Both); 51 pSocket.Close(); 52 }
HttpContext封装上下文
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对象:
1 /// <summary> 2 /// 封装请求报文的信息 3 /// </summary> 4 public class HttpRequest 5 { 6 /* 7 GET /login.aspx HTTP/1.1 8 Accept: text/html, application/xhtml+xml, #1#* 9 Accept-Language: zh-CN 10 User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; QDesk 2.3.1185.202; Windows NT 6.1; Trident/5.0) 11 Accept-Encoding: gzip, deflate 12 Host: localhost:38888 13 Connection: Keep-Alive*/ 14 15 //将报文传进来 16 public HttpRequest(string requestStr) 17 { 18 if(!string.IsNullOrEmpty(requestStr)) 19 { 20 string[] lines=requestStr.Replace("\r\n","\r").Split('\r'); 21 //处理请求的Method 22 this.Method = lines[0].Split(' ')[0]; 23 //设置请求的URL 地址 24 this.RequestURL = lines[0].Split(' ')[1]; 25 } 26 } 27 //是Get 还是set 28 public string Method { get; set; } 29 public string RequestURL { get; set; } 30 }
HttpResponse

1 public class HttpResponse 2 { 3 //请求文件的后缀 4 private string _requestFileExt; 5 public HttpResponse(HttpRequest request) 6 { 7 _requestFileExt = Path.GetExtension(request.RequestURL); 8 } 9 //获取相应提报文字节数组 10 public byte[] BodyData { get; set; } 11 //获取响应头部 12 public byte[] GetHeader() 13 { 14 StringBuilder sb = new StringBuilder(); 15 sb.AppendFormat("HTTP/1.1 200 OK\r\n"); 16 sb.AppendFormat("Content-Type: {0} \r\n", GetContentType(_requestFileExt)); 17 return Encoding.UTF8.GetBytes(sb.ToString()); 18 } 19 20 public string GetContentType(string _requestFileExt) 21 { 22 string type = "text/html"; 23 switch (_requestFileExt) 24 { 25 case ".aspx": 26 case ".html": 27 case ".htm": 28 type = "text/html"; 29 break; 30 case ".png": 31 type = "image/png"; 32 break; 33 case ".gif": 34 type = "image/gif"; 35 break; 36 case ".jpg": 37 case ".jpeg": 38 type = "image/jpeg"; 39 break; 40 case ".css": 41 type = "text/css"; 42 break; 43 case ".js": 44 type = "application/x-javascript"; 45 break; 46 default: 47 type = "text/plain"; 48 break; 49 } 50 return type; 51 } 52 53 //返回响应主体 54 public byte[] GetBodyData() 55 { 56 return BodyData; 57 } 58 }
HttpApplication 中处理
1 public class HttpApplication 2 { public void ProcessRequest(HttpContext context) 3 { 4 string ext = Path.GetExtension(context.Request.RequestURL); 5 switch (ext) 6 { 7 case ".jpg": 8 case ".jpeg": 9 case ".html": 10 case ".htm": 11 case ".css": 12 case ".js": 13 ProcessStaticFile(context); break; 14 case ".aspx": 15 ProcessDynamicFile(context); 16 break; 17 default: 18 ProcessStaticFile(context); 19 break; 20 } 21 } 22 //处理动态页面 23 public void ProcessDynamicFile(HttpContext context) 24 { 25 //假设请求Index.aspx 26 string className=Path.GetFileNameWithoutExtension(context.Request.RequestURL); 27 //获取命名空间 28 string nameSpace = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace; 29 //_02HeimaIIS.IndexPage 30 string fullName = nameSpace + "." + className; 31 //用接口接受不同的实例 32 IHttpHandler obj=(IHttpHandler)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(fullName,true); 33 if (obj == null) 34 { 35 36 } 37 else 38 { 39 obj.ProcessRequest(context); 40 } 41 } 42 //处理静态页面 43 public void ProcessStaticFile(HttpContext context) 44 { 45 string currentWebDir = AppDomain.CurrentDomain.BaseDirectory; 46 string fileName=Path.Combine(currentWebDir,context.Request.RequestURL.TrimStart('/')); 47 context.Response.BodyData = File.ReadAllBytes(fileName); 48 } 49 }
如果是静态网页直接返回
如果是动态页面通过反射实现
以上就是面向接口编程
1 public class MyPage : IHttpHandler 2 { 3 public void ProcessRequest(HttpContext context) 4 { 5 //可以访问数据库,就是动态的 6 string strBody = @"<html><head></head><body><h2> big shit y</h2></body></html>"; 7 context.Response.BodyData = Encoding.UTF8.GetBytes(strBody); 8 } 9 }
IIS内部处理的文字总结:
设置一个监听队列,用一个应用程序池中的实例socket A,接受浏览器发送的数据,再从应用程序池中获取一个实例 socket B将接受到的数据进行处理,而 socket A 不断接受浏览器的请求。
socket B处理数据(用到HttpContext HttpApplication MyPage IHandler)
HttpContext
HttpRequest 获取请求的方法 及请求的地址
HttpResponse得到响应体和 响应头
HttpApplication
根据后缀名判断是动态网页还是静态网页
动态网页:通过反射获取命名空间 通过请求地址找到类名 通过反射获取实例转化成接口,调用其方法。
处理完成后,由代理socket发送报文头和报文体