博客园  :: 首页  :: 新随笔  :: 订阅 订阅  :: 管理

C# 使用HttpListener创建简易Web服务器

Posted on 2021-03-04 17:20  PHP-张工  阅读(1113)  评论(0编辑  收藏  举报

因为项目需要,想仅使用winForm实现一个简易的web服务器,对外提供简单的数据交互服务
改进了之前写的WEB服务器 https://www.cnblogs.com/zjfree/p/3696520.html

核心代码如下:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace WebServer
{
    public class HttpServer
    {
        // HTTP服务
        private HttpListener listener = new HttpListener();
        private Thread ThreadListener = null;

        // web根目录
        private string WebPath = AppDomain.CurrentDomain.BaseDirectory + "web\\";

        // 自定义POST处理
        public delegate string EventDo(object sender, HttpListenerRequest request);
        public event EventDo OnEventDo;

        // 消息事件
        public delegate void EventInfo(object sender, string info);
        public event EventInfo OnEventInfo;

        // 最后错误信息
        public string LastErrorInfo = "";

        // 是否调试
        public bool IsDebug = false;

        public HttpServer()
        {
        }

        // 触发消息
        private void showInfo(string str)
        {
            OnEventInfo(this, str);
        }

        // Http服务器启动
        public bool start(int port)
        {
            try
            {
                if (listener.IsListening)
                {
                    return true;
                }

                // 使用本机IP地址监听
                IPAddress[] ipList = Dns.GetHostAddresses(Dns.GetHostName());

                listener.IgnoreWriteExceptions = true;
                listener.Prefixes.Clear();
                string host = "http://127.0.0.1:" + port.ToString() + "/";
                listener.Prefixes.Add(host);
                foreach (IPAddress ip in ipList)
                {
                    if (ip.AddressFamily.Equals(AddressFamily.InterNetwork))
                    {
                        host = "http://" + ip.ToString() + ":" + port.ToString() + "/";
                        if (!listener.Prefixes.Contains(host))
                        {
                            listener.Prefixes.Add(host);
                        }
                    }
                }

                listener.Start();
            }
            catch (Exception ex)
            {
                if (listener.IsListening)
                {
                    listener.Stop();
                }

                LastErrorInfo = "ERROR:HttpServer 启动失败:" + ex.Message;
                showInfo(LastErrorInfo);
                return false;
            }

            ThreadListener = new Thread(() =>
            {
                while (listener.IsListening)
                {
                    try
                    {
                        HttpListenerContext request = listener.GetContext();

                        // 从线程池从开一个新的线程去处理请求
                        ThreadPool.QueueUserWorkItem(processRequest, request);
                    }
                    catch
                    { }
                }
            });
            ThreadListener.Start();
            showInfo("HttpServer:" + port + " 已启动");

            return true;
        }

        // 停止
        public void stop()
        {
            if (listener.IsListening)
            {
                ThreadListener.Abort();
                listener.Stop();
                ThreadListener = null;
            }
        }

        // 是否在运行
        public bool isRun()
        {
            return listener.IsListening;
        }

        // 处理用户请求
        private void processRequest(object listenerContext)
        {
            var context = (HttpListenerContext)listenerContext;
            try
            {
                string filename = context.Request.Url.AbsolutePath.Trim('/');
                if (filename == "")
                {
                    filename = "index.html";
                }

                if (IsDebug)
                {
                    showInfo(context.Request.Url.ToString());
                }

                string[] ext_list = filename.Split('.');
                string ext = "";
                if (ext_list.Length > 1)
                {
                    ext = ext_list[ext_list.Length - 1];
                }

                string path = Path.Combine(WebPath, filename);
                byte[] msg = new byte[0];

                context.Response.StatusCode = (int)HttpStatusCode.OK;

                string expires = DateTime.Now.AddYears(10).ToString("r");

                // 浏览器缓存
                switch (ext)
                {
                    case "html":
                    case "htm":
                        context.Response.ContentType = "text/html";
                        break;
                    case "jpg":
                    case "jpeg":
                    case "jpe":
                        context.Response.ContentType = "image/jpeg";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "png":
                        context.Response.ContentType = "image/png";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "gif":
                        context.Response.ContentType = "image/gif";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "js":
                        context.Response.ContentType = "application/x-javascript";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "css":
                        context.Response.ContentType = "text/css";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "ico":
                        context.Response.ContentType = "application/x-ico";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                    case "txt":
                        context.Response.ContentType = "text/plain";
                        break;
                    case "do":
                        context.Response.AddHeader("Access-Control-Allow-Origin", "*");
                        context.Response.ContentType = "text/plain;charset=utf-8";
                        string strDo = OnEventDo(this, context.Request);
                        msg = Encoding.UTF8.GetBytes(strDo);
                        break;
                    default:
                        context.Response.ContentType = "";
                        context.Response.AddHeader("cache-control", "max-age=315360000, immutable");
                        context.Response.AddHeader("expires", expires);
                        break;
                }

                if (msg.Length == 0)
                {
                    if (!File.Exists(path))
                    {
                        context.Response.ContentType = "text/html";
                        context.Response.StatusCode = (int)HttpStatusCode.NotFound;
                        if (File.Exists(WebPath + "error.html"))
                        {
                            msg = File.ReadAllBytes(WebPath + "error.html");
                        }
                        else
                        {
                            msg = Encoding.Default.GetBytes("404");
                        }
                    }
                    else
                    {
                        msg = File.ReadAllBytes(path);
                    }
                }

                context.Response.ContentLength64 = msg.Length;
                using (Stream s = context.Response.OutputStream)
                {
                    s.Write(msg, 0, msg.Length);
                }

                msg = new byte[0];
                GC.Collect();
            }
            catch (Exception ex)
            {
                showInfo("ERROR:" + ex.Message);
            }
        }
    }
}

 

修改升级

2021-03-11  添加静态资源浏览器缓存
2021-03-12  修复UTF-8编码问题