IIS的內部原理


對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發送報文頭和報文體

  

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM