步步为营-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 实现效果

原文地址:https://www.cnblogs.com/YK2012/p/6954098.html