IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> c# winform利用httplistener封装搭建http服务器 -> 正文阅读

[网络协议]c# winform利用httplistener封装搭建http服务器

使用

 //http服务路由
 Dictionary<string, string> routes = new Dictionary<string, string> {
    {"/index","IndexController"},
 };
 //服务对象
 MyHttpServer httpServer;


 //启动http服务
httpServer = new MyHttpServer(routes);//初始化,传入路由
httpServer.respNotice += dataHandle;//回调方法,接收到http请求时触发
httpServer.Start(12333);//端口

  /// <summary>
  /// 收到请求的回调函数
   /// </summary>
   /// <param name="data">客户端请求的数据</param>
   /// <param name="resp">respon对象</param>
   /// <param name="route">网址路径,如/api/test</param>
   /// <param name="request_type">请求类型,get或者post</param>
   public void dataHandle(Dictionary<string, string> data, HttpListenerResponse resp, string route = "", string request_type = "get")
   {
     
       string controller = routes.ContainsKey(route) ? routes[route] : "";
	  
	  //预定义返回的json数据
       Dictionary<string, string> resp_data = new Dictionary<string, string>();
       resp_data.Add("code", "1");
       resp_data.Add("data", "");
       resp_data.Add("time", "12345");
       resp_data.Add("msg", "ok ");
		
	   //根据路由key的val匹配相应的算法,以下是自己的逻辑
       switch (controller)
       {
           case "IndexController":
               resp_json = JsonConvert.SerializeObject(resp_data);
               //输出结果
               httpServer.responData(resp_json, resp);
               break;
           default:
               httpServer.responData("404", resp);
               break;
       }


   }

MyHttpServer.cs

using HttpListenerPost;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace PaddleOcrService.request.myhttp
{
    public class MyHttpServer
    {
        //创建委托。用于通知
        public delegate void respNoticeDelegate(Dictionary<string, string> data, HttpListenerResponse resp,string route,string request_type = "get");
        public event respNoticeDelegate respNotice;

        private HttpListener listener = new HttpListener();
        private Dictionary<string, string> actionDict = new Dictionary<string, string>();
        private ReturnDataBase respObj;//返回的数据
        public string curr_path = "";
        //接收到的数据
        public Dictionary<string, string> data_rec = new Dictionary<string, string>();
        
        public MyHttpServer(Dictionary<string,string> routes = null)
        {

            if(routes != null)
            {
                //遍历字典路由
                foreach (KeyValuePair<string, string> kvp in routes)
                {
                    AddPrefixes(kvp.Key, kvp.Value);
                   
                }
            }

        }

        public void AddPrefixes(string url, string action)
        {
            actionDict.Add(url, action);
        }

        public void close()
        {
            listener.Stop();//停止监听
            //listener.Close();//释放资源
        }

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

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

            //监听url
            foreach (var item in actionDict)
            {
                var url = string.Format("http://127.0.0.1:{0}{1}", port, item.Key + "/");
                System.Console.WriteLine(url);
                listener.Prefixes.Add(url);  //监听的是以item.Key + "/"+XXX接口
            }

            listener.Start();
            listener.BeginGetContext(Result, null);
            respObj = new ReturnDataBase();


            System.Console.WriteLine("开始监听");
            System.Console.Read();
        }


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

            listener.BeginGetContext(Result, null);
            var context = listener.EndGetContext(asy);
            var req = context.Request;
            var rsp = context.Response;


            //对接口url处理,解析出curr_path也就是当前路由
            string route=HandlerReq(req.RawUrl);//获取当前路由

            //对接口所传数据处理
            Dictionary<string, string> data = new Dictionary<string, string>();
            data= HandleHttpMethod(context,rsp,route);
          
            //将解析后的结果 通知
            dataNoticeEvent(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)
                {
                    获取类名和方法名 格式: class.method
                    //string class_name = actionDict.ContainsKey(route) ? actionDict[route] : "";
                    /传入类名,利用反射创建对象并返回的数据,要返回给接口的
                    //string content = respObj.GetDataMain(class_name, data);

                    // response的outputStream输出数据的问题
                    //方法一:程序以什么码表输出,一定要控制浏览器以什么码表打开
                    //若"text/html;charset=UTF-8"写错,浏览器会提示下载
                    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
            {
                //url : /test?a=1
                System.Console.WriteLine("url : " + url);

                string[] arr_str= url.Split('?');

                if(arr_str.Length > 0)
                {
                    return curr_path = 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>();
            data_rec.Clear();//先清空上一次http接收的数据
            string contentType = context.Request.ContentType == null ? "" : context.Request.ContentType;
            //1. ContentType = multipart/form-data
            if (contentType.Contains("multipart/form-data") )
            {
                //新建解析类(解析post数据)
                HttpListenerPostParaHelper parse = new HttpListenerPostParaHelper(context);
                List<HttpListenerPostValue> list = parse.GetHttpListenerPostValue();
;
                foreach (HttpListenerPostValue item in list)
                {
                    string k = item.name;
                    string value = "";
                    if (item.type == 0)
                    {
                        //文本解析
                         value = Encoding.UTF8.GetString(item.datas).Replace("\r\n", "");
                    }
                    else
                    {
                        //byte数组转文件
                        File.WriteAllBytes(@"D:\test.png", item.datas);
                        value = @"D:\test.png";
                    }
                    dataRecAdd(k,value);
                }
                return_data = data_rec;
              
                return return_data;
            }


            //2.ContentType=application/json
            if (contentType.Contains("application/json"))
            {
                try
                {
                    Stream stream = context.Request.InputStream;
                    StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                    string json = reader.ReadToEnd();
                    Dictionary<string, string> DicContent = new Dictionary<string, string>();
                    if (string.IsNullOrEmpty(json)) return return_data ;
                    if (json == "[]" || json == "") return return_data;
                    data_rec = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
                    return_data = data_rec;//返回的数据
                   
                }
                catch (Exception ex)
                {
                    return return_data;
                }
                return return_data;
            }




            //3. ContentType = text/html等类型 就使用别的解析算法
            switch (context.Request.HttpMethod)
            {
                case "GET":
                    var data = context.Request.QueryString;
                    // 没解决乱码问题,用url进行解析正常
                    string url = context.Request.Url.ToString();
                    string[] pars = url.Split('?');
                    string content = "";
                    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('=');
                            dataRecAdd(messages[0], messages[1]);
                            //content += "参数为:" + messages[0] + " 值为:" + messages[1];
                        }
                        return_data = data_rec;
                    }

                   
                    return return_data;
                    break;
            }


            return return_data;

        }

        /// <summary>
        /// 将解析后的数据通知事件
        /// </summary>
        /// <param name="data">解析后的字典数据</param>
        /// <param name="rsp">respon对象</param>
        /// <param name="route">路由</param>
        /// <param name="method">方法</param>
        public void dataNoticeEvent(Dictionary<string, string> data,HttpListenerResponse rsp,string route, string method = "unkonwn")
        {
            //通知
            //if (data_rec.Count > 1)
            //{
            //    respNotice?.Invoke(data_rec, rsp,route,method);
            //}

            respNotice?.Invoke(data, rsp, route, method);

        }

        public void dataRecAdd(string k ,string v)
        {
            if (data_rec.ContainsKey(k))
            {
                data_rec[k] = v;
            }
            else
            {
                data_rec.Add(k, v);
            }
        }

    }

    class ReturnDataBase
    {
        public string GetDataMain(string class_method, Dictionary<string, string> rec_data)
        {
            string[] class_arr = class_method.Split('.');//分割类名跟方法
           
            string class_name,method;
            if (class_arr.Length == 1) class_name = class_arr[0];
            if (class_arr.Length == 2) method = class_arr[1];
            if (class_arr.Length == 0) return "";

            return "cesh";
        }
    }




}

HttpListenerPostValue.cs

这个类主要用于解析content-type为multipart/form-data时解析数据

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
 
namespace HttpListenerPost
{
    /// <summary>
    /// HttpListenner监听Post请求参数值实体
    /// </summary>
    public class HttpListenerPostValue
    {
        /// <summary>
        /// 0=> 参数
        /// 1=> 文件
        /// </summary>
        public int type = 0;
        public string name;
        public byte[] datas;
    }
 
    /// <summary>
    /// 获取Post请求中的参数和值帮助类
    /// </summary>
    public class HttpListenerPostParaHelper
    {
        private HttpListenerContext request;
 
        public HttpListenerPostParaHelper(HttpListenerContext request)
        {
            this.request = request;
        }
 
        private bool CompareBytes(byte[] source, byte[] comparison)
        {
            try
            {
                int count = source.Length;
                if (source.Length != comparison.Length)
                    return false;
                for (int i = 0; i < count; i++)
                    if (source[i] != comparison[i])
                        return false;
                return true;
            }
            catch
            {
                return false;
            }
        }
 
        private byte[] ReadLineAsBytes(Stream SourceStream)
        {
            var resultStream = new MemoryStream();
            while (true)
            {
                int data = SourceStream.ReadByte();
                resultStream.WriteByte((byte)data);
                if (data == 10)
                    break;
            }
            resultStream.Position = 0;
            byte[] dataBytes = new byte[resultStream.Length];
            resultStream.Read(dataBytes, 0, dataBytes.Length);
            return dataBytes;
        }
 
        /// <summary>
        /// 获取Post过来的参数和数据
        /// </summary>
        /// <returns></returns>
        public List<HttpListenerPostValue> GetHttpListenerPostValue()
        {
            try
            {
                List<HttpListenerPostValue> HttpListenerPostValueList = new List<HttpListenerPostValue>();
                if (request.Request.ContentType.Length > 20 && string.Compare(request.Request.ContentType.Substring(0, 20), "multipart/form-data;", true) == 0)
                {
                    string[] HttpListenerPostValue = request.Request.ContentType.Split(';').Skip(1).ToArray();
                    string boundary = string.Join(";", HttpListenerPostValue).Replace("boundary=", "").Trim();
                    byte[] ChunkBoundary = Encoding.UTF8.GetBytes("--" + boundary + "\r\n");
                    byte[] EndBoundary = Encoding.UTF8.GetBytes("--" + boundary + "--\r\n");
                    Stream SourceStream = request.Request.InputStream;
                    var resultStream = new MemoryStream();
                    bool CanMoveNext = true;
                    HttpListenerPostValue data = null;
                    while (CanMoveNext)
                    {
                        byte[] currentChunk = ReadLineAsBytes(SourceStream);
                        if (!Encoding.UTF8.GetString(currentChunk).Equals("\r\n"))
                            resultStream.Write(currentChunk, 0, currentChunk.Length);
                        if (CompareBytes(ChunkBoundary, currentChunk))
                        {
                            byte[] result = new byte[resultStream.Length - ChunkBoundary.Length];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            CanMoveNext = true;
                            if (result.Length > 0)
                                data.datas = result;
                            data = new HttpListenerPostValue();
                            HttpListenerPostValueList.Add(data);
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
 
                        }
                        else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Disposition"))
                        {
                            byte[] result = new byte[resultStream.Length - 2];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            CanMoveNext = true;
                            data.name = Encoding.UTF8.GetString(result).Replace("Content-Disposition: form-data; name=\"", "").Replace("\"", "").Split(';')[0];
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
                        }
                        else if (Encoding.UTF8.GetString(currentChunk).Contains("Content-Type"))
                        {
                            CanMoveNext = true;
                            data.type = 1;
                            resultStream.Dispose();
                            resultStream = new MemoryStream();
                        }
                        else if (CompareBytes(EndBoundary, currentChunk))
                        {
                            byte[] result = new byte[resultStream.Length - EndBoundary.Length - 2];
                            resultStream.Position = 0;
                            resultStream.Read(result, 0, result.Length);
                            data.datas = result;
                            resultStream.Dispose();
                            CanMoveNext = false;
                        }
                    }
                }
                return HttpListenerPostValueList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
    }
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 18:20:11  更:2022-04-18 18:23:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:50:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码