设为首页 收藏本站
查看: 997|回复: 0

[经验分享] IIS的内部原理

[复制链接]

尚未签到

发表于 2015-8-12 10:54:01 | 显示全部楼层 |阅读模式
  对IIS只有表面的理解   现在模拟一下IIS的内部原理:


DSC0000.gif DSC0001.gif 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发送报文头和报文体
  
  
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-97848-1-1.html 上篇帖子: 网站SEO优化、IIS日志分析工具 IISLogViewer V2.0 发布 下篇帖子: 一键安装IIS的点点滴滴——For所有Microsoft的操作系统(上)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表