C# 简单封装HttpListener创建Http服务,利用反射调用请求处理方法

http服务类HttpServer,目前只处理contentType ="application/x-www-form-urlencoded"的请求

class HttpServer
    {
        //创建委托。用于调用相应请求处理
        public delegate void respNoticeDelegate(Dictionary<string, string> data, HttpListenerResponse resp, string route
            , string request_type = "get");
        public event respNoticeDelegate respNotice;
        private HttpListener listener ;

        public HttpServer()
        {
            listener = new HttpListener();           
        }

        public void close()
        {
            listener.Stop();//停止监听
        }

        //开始监听
        public void Start(int port)
        {
            if (!HttpListener.IsSupported)
            {
                Console.WriteLine("无法在当前系统上运行服务" + DateTime.Now.ToString());
                return;
            }

            if (port == 0)
            {
                System.Console.WriteLine("没有监听端口");
            }

            var url = string.Format("http://127.0.0.1:{0}{1}", port, "/");
            System.Console.WriteLine(url);
            listener.Prefixes.Add(url);  //监听 
            listener.Start();
            listener.BeginGetContext(GetContextCallBack, listener);
        
        }

        private void GetContextCallBack(IAsyncResult asy)
        {
            listener = asy.AsyncState as HttpListener;
            if (!listener.IsListening) return;//如果已经停止监听了就直接返回

            listener.BeginGetContext(new AsyncCallback(GetContextCallBack), listener);
            var context = listener.EndGetContext(asy);
            var req = context.Request;
            var rsp = context.Response;
            //对接口url处理
            string route = HandlerReq(req.RawUrl);//获取当前路由
            //解析接口参数
            Dictionary<string, string> data = new Dictionary<string, string>();
            data = HandleHttpMethod(context, rsp, route);
            //将解析后的结果 通知
            doNoticeEvent(data, rsp, route, context.Request.HttpMethod);
        }

        /// <summary>
        /// 输出结果(返回结果)
        /// </summary>
        /// <param name="content">结果</param>
        /// <param name="rsp">httprespon对象</param>
        /// <returns></returns>
        public string responData(string content, HttpListenerResponse rsp)
        {
            try
            {
                using (var stream = rsp.OutputStream)
                {
                    rsp.StatusCode = 200;
                    rsp.ContentType = "text/html;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
                    rsp.AddHeader("Content-type", "application/json");//添加响应头信息
                    rsp.ContentEncoding = Encoding.UTF8;
                    //后台跨域请求;允许跨域,必须配置
                    rsp.AppendHeader("Access-Control-Allow-Origin", "*");//允许跨域
                    rsp.AppendHeader("Access-Control-Allow-Credentials", "true");
                    rsp.AppendHeader("Access-Control-Allow-Headers", "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,X-Requested-With");
                    rsp.AppendHeader("Access-Control-Max-Age", "86400");

                    byte[] dataByte = Encoding.UTF8.GetBytes(content);
                    stream.Write(dataByte, 0, dataByte.Length);
                    stream.Close();
                }
            }
            catch (Exception e)
            {
                rsp.Close();
                return e.Message;
            }
            rsp.Close();
            return "";
        }
        /// <summary>
        /// 对客户端来的url处理
        /// </summary>
        /// <param name="url"></param>
        private string HandlerReq(string url)
        {
            try
            {
                string[] arr_str = url.Split('?');

                if (arr_str.Length > 0)
                {
                    return  arr_str[0];//如下:/api/test
                }

                return "";
            }
            catch (Exception e)
            {
                return "";
            }
        }
        //处理接口所传数据 Post和Get 获取数据
        private Dictionary<string, string> HandleHttpMethod(HttpListenerContext context, HttpListenerResponse resp, string route)
        {
            Dictionary<string, string> return_data = new Dictionary<string, string>();
            try {
                string contentType = context.Request.ContentType == null ? "" : context.Request.ContentType;
                if (contentType == "application/x-www-form-urlencoded")
                {
                    switch (context.Request.HttpMethod)
                    {
                        case "GET":
                            var data = context.Request.QueryString;
                            string url = context.Request.Url.ToString();
                            string[] pars = url.Split('?');
                            if (pars.Length == 0)
                            {
                                return return_data;
                            }
                            if (pars.Length <= 1) return return_data;
                            string canshus = pars[1];
                            if (canshus.Length > 0)
                            {
                                string[] canshu = canshus.Split('&');
                                foreach (string i in canshu)
                                {
                                    string[] messages = i.Split('=');
                                    datazParamAdd(messages[0], messages[1], return_data);
                                }
                            }
                            break;
                        case "POST":
                            using (Stream stream = context.Request.InputStream)
                            {
                                StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                                string strParam = reader.ReadToEnd();
                                System.Console.WriteLine(strParam);
                                string[] keyValue = strParam.Split('&');
                                foreach (string param in keyValue)
                                {
                                    string[] kv = param.Split('=');
                                    datazParamAdd(kv[0], kv[1], return_data);
                                }
                            }
                            break;
                    }
                }
            }catch(Exception ex)
            {
                System.Console.WriteLine("err:" + ex.Message);
            }
            return return_data;

        }

        /// <summary>
        /// 将解析后的参数通知事件
        /// </summary>
        /// <param name="data">解析后的参数字典</param>
        /// <param name="rsp">respon对象</param>
        /// <param name="route">路由</param>
        /// <param name="method">请求方法</param>
        public void doNoticeEvent(Dictionary<string, string> data, HttpListenerResponse rsp, string route, string method = "")
        {
            //调用请求处理代理方法
            respNotice?.Invoke(data, rsp, route, method);

        }

        public void datazParamAdd(string k, string v, Dictionary<string, string> dataParam)
        {
            if (dataParam.ContainsKey(k))
            {
                dataParam[k] = v;
            }
            else
            {
                dataParam.Add(k, v);
            }
        }

    }

在winform界面中启动服务和调用处理,请求处理基类为BaseController,派生类DllController

class BaseController
    {

    }

class DllController : BaseController
    {
        public string getKey(string method, string seed)
        {
            //在这里处理http请求的业务逻辑

            return "处理结果";
        }
    }

winform页面代码,采用多线程调用处理类,利用反射,根据请求路径,给对应的方法参数传值并执行

public partial class FrmWebserver : Form
    {
        HttpServer httpServer;
        //加载程序集,用于反射
        Assembly assembly = Assembly.Load("fcar_webserver");
        Type dllControllerType = null;
        //http服务路由对应的处理接口类
        Dictionary<string, BaseController> httpRoutes = new Dictionary<string, BaseController>();
        public FrmWebserver()
        {
            InitializeComponent();
        }

        private void FrmWebserver_Load(object sender, EventArgs e)
        {
            //在这里配置请求路径对应的接口处理类,单例模式
            DllController dllController = new DllController();
            httpRoutes.Add("/keyDll/getKey", dllController);
            httpServer = new HttpServer();
            httpServer.respNotice += dataHandle;//回调方法,接收到http请求时触发
            ThreadPool.SetMinThreads(3, 3);//配置线程池
            ThreadPool.SetMaxThreads(100, 100);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            try {
                if (btnStart.Text == "启动")
                {
                    httpServer.Start(int.Parse(txtPort.Text));
                    btnStart.Text = "关闭";
                }
                else
                {
                    httpServer.close();
                    this.Close();
                }
            }catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /// <summary>
        /// 收到请求的回调函数
        /// </summary>
        /// <param name="data">客户端请求的数据</param>
        /// <param name="resp">respon对象</param>
        /// <param name="route">请求路径,如/keyDll/getKey</param>
        /// <param name="request_type">请求类型,get或者post</param>
        public void dataHandle(Dictionary<string, string> data, HttpListenerResponse resp, string route = "", string request_type = "get")
        {
            //采用线程池,提高并发处理
            ThreadPool.QueueUserWorkItem(p =>
            {
                Result result = new Result();
                result.success = false;
                try
                {
                    BaseController controller = httpRoutes.ContainsKey(route) ? httpRoutes[route] : null;
                    if (route.StartsWith("/keyDll"))
                    {
                        //根据方法名通过反射,执行对应的方法
                        string methodName = route.Substring(route.LastIndexOf("/") + 1);
                        DllController dllController = (DllController)controller;
                        if (dllControllerType == null)
                            dllControllerType = assembly.GetType("fcar_webserver.DllController");
                        MethodInfo methodInfo = dllControllerType.GetMethod(methodName);
                        List<object> objectList = new List<object>();
                        foreach (ParameterInfo parameterInfoItem in methodInfo.GetParameters())
                        {
                            if (data.ContainsKey(parameterInfoItem.Name))
                            {
                                if (parameterInfoItem.ParameterType == typeof(String))
                                {
                                    objectList.Add(data[parameterInfoItem.Name]);
                                }
                                else if (parameterInfoItem.ParameterType == typeof(int))
                                {
                                    objectList.Add(int.Parse(data[parameterInfoItem.Name]));
                                }
                            }
                        }
                        if (objectList.Count == methodInfo.GetParameters().Length)
                        {
                            string strBack = methodInfo.Invoke(dllController, objectList.ToArray()).ToString();
                            result.success = true;
                            result.data = strBack;
                        }
                        else
                        {
                            result.msg = "参数不对!";
                        }
                    }
                    else
                    {
                        result.code = 404;
                        httpServer.responData("404", resp);
                    }
                }
                catch (Exception ex)
                {
                    System.Console.WriteLine(ex.Message);
                    result.msg = "请求失败";
                }
                httpServer.responData(JsonConvert.SerializeObject(result), resp);
            });    
        }

    }

返回结果类

public class Result
    {
        public bool success { get; set; }//结果
        public String msg { get; set; }//结果信息
        public Object data { get; set; }
        public Object result { get; set; }//
        public int code { get; set; }//
        public String token { get; set; }//请求接口的凭证

        public Result(bool result, String msg, Object data)
        {
            this.success = result;
            this.msg = msg;
            this.data = data;
        }

        public Result(bool result, String msg)
        {
            this.success = result;
            this.msg = msg;
        }

        public Result()
        {
        }


        
    }

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值