zoukankan      html  css  js  c++  java
  • 步步为营-67-模拟服务器与浏览器的交互

    说明:服务器和浏览器之间通信大致通过:连接->请求->处理->响应等过程

    1 创建服务器(form应用程序)

    1.1 首先需要两个对象 Request 和 Response

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
        //请求报文
       public class HttpRequest
        {
           //请求方式-属性
            public string Method { get; set; }
            //请求地址-属性
            public string Url { get; set; }
            //请求版本-属性
            public string Protocol { get; set; }
    
           //构造方法
            public HttpRequest(string strRequest)
            {
                //此时head Get http://baidu.com... HTTP/1.1
               string head = strRequest.Replace("
    ", "$").Split('$')[0];
                String  [] headList = head.Split(' ');
                Method = headList[0];
                //将请求文件转成绝对路径
                Url = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), headList[1].Substring(1));
                Protocol = headList[2];
            }
        }
    }
     
    HttpRequest
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
        public class HttpResponse
        {
            public HttpResponse(HttpRequest request)
            {
                //url /a/b.html
                //获取文件扩展名--确定类型
                type = GetType(Path.GetExtension(request.Url));
                //获取文件大小
            }
    
            public int Length { set; get; }
            private string type;
    
    
            #region  04-属性-响应报文头
            public byte[] Head
            {
                get
                {
                    byte[] bs;
    
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("HTTP/1.1 200 OK");
                    sb.AppendLine("Dage: " + DateTime.Now);
                    sb.AppendLine("Server: XYXTL");
                    sb.AppendLine("Content-Length: " + Length);
                    sb.AppendLine("Content-Type: " + type);
                    sb.AppendLine();
                    bs = Encoding.UTF8.GetBytes(sb.ToString());
                    return bs;
                }
            } 
            #endregion
    
            #region 05-方法 获取响应报文的类型
    
            private string GetType(string ext)
            {
                string type = "text/html;charset=urf-8";
    
                switch (ext)
                {
                    case ".aspx":
                    case ".html":
                    case ".htm":
                        type = "text/html;charset=urf-8";
                        break;
                    case ".png":
                        type = "image/png";
                        break;
                    case ".gif":
                    case ".GIF":
                        type = "image/gif";
                        break;
                    case ".jpg":
                    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;
            }
    
    
            #endregion
    
            #region  05-属性-响应报文体
            public byte[] Body
            {
                get ; set ;
            }
            #endregion
        }
    }
    HttpResponse

    1.2 将对象进一步封装  Context

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
       public class HttpContext
        {
            public HttpRequest Request { set; get; }
            public HttpResponse Response { set; get; }
    
            public HttpContext(string str)
            {
                Request = new HttpRequest(str);
                Response = new HttpResponse(Request);
            }
    
        }
    }
    HttpContext

    1.3 如果是静态方法直接获取,如果是动态的需要进一步定位到响应的cs文件中

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Net.Sockets;
    using System.Reflection;
    using System.Text;
    using System.Text.RegularExpressions;
    using System.Threading.Tasks;
    
    namespace Service
    {
       public class HttpApplication
        {
           public void ProcessRequest(HttpContext context, Socket clientSok)
            {
                //根据文件的扩展名,判断是否为动态文件
                string ext = Path.GetExtension(context.Request.Url);
                if (ext == ".aspx")
                {
                    //动态文件
                    //01 获取请求的名称--C:ac.aspx === c
                    string className = Regex.Match(context.Request.Url,@".+\(.+).aspx").Groups[1].Value;
                    //02 根据名字 反射类
                    IHttpHandeler handel = Assembly.GetExecutingAssembly().CreateInstance("Service." + className) as IHttpHandeler;
                    handel.ProcessRequest(context);
                }
                else  
                {
                    //静态文件--直接把字节数组交给file读取
                    byte [] bs = File.ReadAllBytes(context.Request.Url);
                    context.Response.Length = bs.Length;
                    context.Response.Body = bs;
                  
                }
                clientSok.Send(context.Response.Head);
                clientSok.Send(context.Response.Body);
            }
    
           
        }
    }
    HttpApplication

    1.4 动态--通过接口和反射实现

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
       public interface IHttpHandeler
        {
           void ProcessRequest(HttpContext context);
        }
    }
    IHttpHandeler
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace Service
    {
       public class yk:IHttpHandeler
        {
            public void ProcessRequest(HttpContext context)
            {
                string str = "<b>逍遥小天狼</b>";
                byte [] bs = Encoding.UTF8.GetBytes(str);
                context.Response.Body = bs;
                context.Response.Length = bs.Length;
    
            }
        }
    }
    yk

    1.5 实现效果

  • 相关阅读:
    Windows server 2016 解决“无法完成域加入,原因是试图加入的域的SID与本计算机的SID相同。”
    Windows Server 2016 辅助域控制器搭建
    Windows Server 2016 主域控制器搭建
    Net Framework 4.7.2 覆盖 Net Framework 4.5 解决办法
    SQL SERVER 2012更改默认的端口号为1772
    Windows下彻底卸载删除SQL Serever2012
    在Windows Server2016中安装SQL Server2016
    SQL Server 创建索引
    C#控制台或应用程序中两个多个Main()方法的设置
    Icon cache rebuilding with Delphi(Delphi 清除Windows 图标缓存源代码)
  • 原文地址:https://www.cnblogs.com/YK2012/p/6954098.html
Copyright © 2011-2022 走看看