因为项目需要,想仅使用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编码问题