美文网首页
HTTP与IIS服务浅入

HTTP与IIS服务浅入

作者: Memoyu | 来源:发表于2019-04-29 15:26 被阅读0次

  认知尚浅,如有错误,愿闻其详!

  最近刚接触ASP.NET,在此之前对于Web开发方面没有过多的了解,更不懂得浏览器访问网页的整个大概的过程经历了什么,整个思维模式仍停留在客户端开发C/S模式下,所以,有个比较浅显的制作简单IIS服务器例子来搞懂ASP.NET的大概处理过程来过渡,尤为重要。那我们就来学习这个例子。

  首先,我们了解一下HTTP是啥?

  HTTP是一种传输协议,全称(HyperText Transfer Protocol)超文本传输协,目的是为了规范请求与接收HTML页面的方法。只有根据协议包装报文数据(请求报文,响应报文),才能够正常的解析与处理响应。报文具体结构如下:
HTTP请求报文:

请求报文.png

其结构分为请求头、状态行、空行和请求体(GET则为空)四个部分组成,上图给为请求报文>的一般格式。

HTTP响应报文:

响应报文.png

响应报文与请求报文结构类似,如上图。

详情可转至该文:https://blog.csdn.net/lhx_ldm/article/details/80338211

IIS服务

IIS全称Internet Information Service,中文名:Internet信息服务,专用于微软操作系统平台,兼容微软的各项Web技术,尤其是ASP.NET。用于Web网页的浏览的信息处理,也就是网站服务器。其处理ASP.NET的大概过程如下图。


ASP请求编译流程图.png

详情可转至该文:https://blog.csdn.net/qq_35393869/article/details/81182237

SimpleIIS例子

这是我在学习的过程中做的思维导图,如下图,然后根据思维导图再做出项目。IIS其内部处理简单的分为三大块:请求报文解析(HttpRequest)、报文处理(HttpApplication)、响应报文回传(HttpResponse),其基本的通信是通过Socket通信来实现,

SimpleIIS.png

代码

由于项目文件挺多的,代码量也挺多,篇幅过大,就不一一展示
服务器端
服务器不断地侦听接收客户端发来的请求,然后进行处理
服务端参考Socket实现:https://www.cnblogs.com/memoyu/p/10764884.html

 //1、初始化解析 请求报文 。
HttpContext context = new HttpContext(msgStr);

//2、处理请求报文,处理响应报文。
HttpApplicaton applicaton = new HttpApplicaton();
applicaton.ProcessRequest(context);
//3、返回响应内容
proxSocket.Send(context.httpResponse.GetHttpResponseHeader());//返回响应头
proxSocket.Send(context.httpResponse.body);
//4、关闭连接
proxSocket.Shutdown(SocketShutdown.Both);
proxSocket.Close();

处理请求信息(HttpApplication)
获取HttpRequest解析的请求头信息,然后对请求信息进行处理,本质是对HTML的解析,与动态页面的数据填充和整合,然后响应给客户端。请求可是请求静态页面和动态页面,静态页面直接将数据组合入响应体返回,动态页面则需要执行C#代码(执行的方式是通过反射,然后创建IHttpHandler对象,执行接口方法ProcessRequest方法),然后将动态数据组合入响应体返回。

 /// <summary>
        /// 实现接口,处理报文
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            #region 处理动态文件请求
            string ext = Path.GetExtension(context.httpRequest.url);//通过请求的地址获得请求文件拓展名
            if (ext == ".aspx")//如果是.aspx文件
            {
                //通过反射的方式去实例化对应类,执行其内部方法,实现处理动态页面
                var className = Path.GetFileNameWithoutExtension(context.httpRequest.url);//获得不具有拓展名的路径
                IHttpHandler obj = Assembly.Load("SimpleIIS").CreateInstance("SimpleIIS." + className) as IHttpHandler;//通过反射创建对象
                obj.ProcessRequest(context);//执行动态页面处理
                return;
            }
            #endregion
            #region 静态页面处理
            //获得请求路径
            // context.httpRequest.url  例如:/web/sujin.html  相对路径
            string basePath = AppDomain.CurrentDomain.BaseDirectory;//获取程序的bin/Debug目录,相当于网站的根目录,
            string fileName = Path.Combine(basePath, context.httpRequest.url.TrimStart('/'));//拼接url 获得请求页面的绝对路径  ,源于url地址开头带有/,所以需要先去除在拼接
            if (!File.Exists(fileName))//判断请求文件是否存在
            {
                context.httpResponse.stateCode = "404";//设置响应报文参数
                context.httpResponse.stateDescribe = "Not Found";
                context.httpResponse.contentType = "text/html";
                string noExistHtml = Path.Combine(basePath , @"web\404.html");//拼接404页面地址
                context.httpResponse.body = File.ReadAllBytes(noExistHtml);//将404.html页面加入响应体
            }
            else
            {
                context.httpResponse.stateCode = "200";//设置响应报文参数
                context.httpResponse.stateDescribe = "Ok";
                context.httpResponse.contentType = GetContentType(Path.GetExtension(context.httpRequest.url));//获得请求文件类型
                context.httpResponse.body = File.ReadAllBytes(fileName);//将请求文件写加入响应体
            }

            #endregion

        }
        /// <summary>
        /// 根扩展名获得请求的文件类型
        /// </summary>
        /// <param name="ext">扩展名</param>
        /// <returns>响应文件类型</returns>
        public string GetContentType(string ext)
        {
            string type = "text/html; charset=UTF-8";
            switch (ext)
            {
                case ".aspx":
                case ".html":
                case ".htm":
                    type = "text/html; charset=UTF-8";
                    break;

                case ".png":
                    type = "image/png";
                    break;
                case ".gif":
                    type = "image/gif";
                    break;
                case ".jpg":
                    type = "image/jpg";
                    break;
                case ".jpeg":
                    type = "image/jpeg";
                    break;
                case ".css":
                    type = "text/css";
                    break;
                case ".js":
                    type = "application/x-javascript";
                    break;
                default:
                    type = "text/plain; charset=gbk";
                    break;
            }
            return type;
        }

请求头的处理(HttpRequest)

  /// <summary>
        /// 请求解析构造函数,解析请求,对应赋值属性
        /// </summary>
        /// <param name="requestStr"></param>
        /* 
         * 请求体:
         GET / HTTP/1.1
         Host: 192.168.0.4:45000
         Connection: keep-alive
         Upgrade-Insecure-Requests: 1
         User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36
         Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,;q=0.8,application/signed-exchange;v=b3
         Accept-Encoding: gzip, deflate
         Accept-Language: zh-CN,zh;q=0.9
         */
        public HttpRequest(string requestStr)
        {
            string[] lines = requestStr.Replace("\r\n" , "\r").Split('\r'); //源于splite只能处理单个字符,所以的将\r\n替换成\r
            httpMethod = lines[0].Split(' ')[0];//赋值请求的方法
            url = lines[0].Split(' ')[1];//赋值请求连接
            httpVersion = lines[0].Split(' ')[2];//赋值http版本号
        }

响应报文处理(HttpResponse)

 /// <summary>
        /// 拼接响应头数据
        /// </summary>
        /// <returns></returns>
        public byte[] GetHttpResponseHeader()
        {
            string strResponseHeader = string.Format(@"HTTP/1.1 {0} {1}
Content-Type: {2}
Accept-Ranges: bytes
server: Microsoft-IIS/8.5
X-Powered-By: ASP.NET
Date: Sat, 23 Nov 2019 08:43:15
Content-Length: {3}

",stateCode , stateDescribe , contentType , body.Length);

            return Encoding.Default.GetBytes(strResponseHeader);
        }

模拟动态页面
一般状况下,我们访问的网页都是动态的,所以,实现动态网页功能是必要的,我们不仅可以请求静态页面,动态的也需要处理,ASP.NET中动态页面为.aspx 和 .ashx,类似如下结构。

 public class DynamicPage_1 : IHttpHandler
    {
        /// <summary>
        /// 实现接口方法
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            string str = string.Format("<html><head></head><body><h3>{0}<h3></body></html>", DateTime.Now.ToString());//动态生成html内容,时间

            context.httpResponse.stateCode = "200";//赋值响应头
            context.httpResponse.stateDescribe = "Ok";
            context.httpResponse.contentType = "text/html";
            context.httpResponse.body = Encoding.Default.GetBytes(str);//赋值响应体
        }
    }

效果展示

我在bin/Debug/web目录下放了保存的两个静态页面.


静态页面.png SimpleIIS.gif

相关文章

网友评论

      本文标题:HTTP与IIS服务浅入

      本文链接:https://www.haomeiwen.com/subject/kbbagqtx.html