|
对IIS只有表面的理解 现在模拟一下IIS的内部原理:
View Code
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
View Code
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发送报文头和报文体
|
|