引言 |
此篇是《【轮子狂魔】抛弃IIS,向天借个HttpListener - 基础篇(附带源码)》的续篇,也可以说是提高篇,如果你对HttpListener不甚了解的话,建议先看下基础篇。
这次玩的东西有点多了,大致分为如下几个方向:
1.支持静态页面
2.Ur映射l执行方法
3.Url映射执行Lua脚本
4.模仿MVC中的C
这些东西有什么用? |
支持静态页面:这个纯属玩具吧,只是基础篇作为引子的一个简单示例而已。
Url映射执行方法:类似Web API,可以提供一些基于Http协议的交互方式。
Url映射执行Lua脚本:与上面一样,不同的是,在某些场景下更合适,比如业务频繁变动、频繁发布。Lua脚本我就不细说了,不清楚的可以百度一下,是个很好玩的东西。
模仿MVC中的C:这个实例只是想说基于HttpListener我们可以做很多事情,如果你对asp.net、MVC很熟悉,你可以做个整整的Web Server出来,甚至做个Web框架都可以。
那么除了这些还可以做什么?
其实太多了,比如反向代理、负载均衡、黑名单等等,你都可以做。如果你有兴趣可以跟帖讨论 ^_^
改造HttpServer支持横向扩展 |
抽离出一个接口:HttpImplanter
1 interface HttpImplanter2 {3 void Start();4 void Stop();5 void MakeHttpPRefix(HttpListener server);6 ReturnCode ProcessRequest(HttpListenerContext context);7 byte[] CreateReturnResult(HttpListenerContext context, ReturnCode result);8 }View Code
改造HttpServer的一些执行细节
1 /// <summary> 2 /// 可接收Http请求的服务器 3 /// </summary> 4 class HttpServer 5 { 6 Thread _httpListenThread; 7 8 /// <summary> 9 /// HttpServer是否已经启动 10 /// </summary> 11 volatile bool _isStarted = false; 12 13 /// <summary> 14 /// 线程是否已经结束 15 /// </summary> 16 volatile bool _terminated = false; 17 volatile bool _ready = false; 18 volatile bool _isRuning = false; 19 HttpImplanter _httpImplanter; 20 21 public void Start(HttpImplanter httpImplanter) 22 { 23 if (!HttpListener.IsSupported) 24 { 25 Logger.Exit("不支持HttpListener!"); 26 } 27 28 if (_isStarted) 29 { 30 return; 31 } 32 _isStarted = true; 33 _ready = false; 34 _httpImplanter = httpImplanter; 35 36 RunHttpServerThread(); 37 38 while (!_ready) ; 39 } 40 41 private void RunHttpServerThread() 42 { 43 _httpListenThread = new Thread(new ThreadStart(() => 44 { 45 HttpListener server = new HttpListener(); 46 try 47 { 48 _httpImplanter.MakeHttpPrefix(server); 49 server.Start(); 50 } 51 catch (Exception ex) 52 { 53 Logger.Exit("无法启动服务器监听,请检查网络环境。"); 54 } 55 56 _httpImplanter.Start(); 57 58 IAsyncResult result = null; 59 while (!_terminated) 60 { 61 while (result == null || result.IsCompleted) 62 { 63 result = server.BeginGetContext(new AsyncCallback(ProcessHttpRequest), server); 64 } 65 _ready = true; 66 Thread.Sleep(10); 67 } 68 69 server.Stop(); 70 server.Abort(); 71 server.Close(); 72 _httpImplanter.Stop(); 73 } 74 )); 75 76 _httpListenThread.IsBackground = true; 77 _httpListenThread.Start(); 78 } 79 80 private void ProcessHttpRequest(IAsyncResult iaServer) 81 { 82 HttpListener server = iaServer.AsyncState as HttpListener; 83 HttpListenerContext context = null; 84 try 85 { 86 context = server.EndGetContext(iaServer); 87 Logger.Info("接收请求" + context.Request.Url.ToString()); 88 //判断上一个操作未完成,即返回服务器正忙,并开启一个新的异步监听 89 if (_isRuning) 90 { 91 Logger.Info("正在处理请求,已忽略请求" + context.Request.Url.ToString()); 92 RetutnResponse(context, _httpImplanter.CreateReturnResult(context, new ReturnCode((int)CommandResult.ServerIsBusy, EnumHelper.GetEnumDescription(CommandResult.ServerIsBusy)))); 93 server.BeginGetContext(new AsyncCallback(ProcessHttpRequest), server); 94 return; 95 } 96 97 _isRuning = true; 98 server.BeginGetContext(new AsyncCallback(ProcessHttpRequest), server); 99 }100 catch101 {102 Logger.Warning("服务器已关闭!");103 return;104 }105 106 string scriptName = new UrlHelper(context.Request.Url).ScriptName;107 byte[] resultBytes = null;108 if (scriptName.ToLower().EndsWith(".html")||scriptName == "favicon.ico")109 {110 string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Web", scriptName);111 if (File.Exists(filePath))112 {113 resultBytes = File.ReadAllBytes(filePath);114 }115 else116 {117 resultBytes = _httpImplanter.CreateReturnResult(context, new ReturnCode((int)CommandResult.FileNotExists, EnumHelper.GetEnumDescription(CommandResult.FileNotExists)));118 }119 }120 else121 {122 ReturnCode result = _httpImplanter.ProcessRequest(context);123 resultBytes = _httpImplanter.CreateReturnResult(context, result);124 }125 RetutnResponse(context, resultBytes);126 _isRuning = false;127 }128 129 private static void RetutnResponse(HttpListenerContext context, byte[] resultBytes)130 {131 context.Response.ContentLength64 = resultBytes.Length;132 System.IO.Stream output = context.Response.OutputStream;133 try134 {135 output.Write(resultBytes, 0, resultBytes.Length);136 output.Close();137 }138 catch139 {140 Logger.Warning("客户端已经关闭!");141 }142 }143 144 public void Stop()145 {146 if (!_isStarted)147 {148 return;149 }150 151 _terminated = true;152 _httpListenThread.Join();153 154 _isStarted = false;155 }156 157 }View Code
Url映射执行方法 |
1.继承HttpImplanter
2.增加监听前缀,用于过滤Url
3.创建返回结果
3.1 解析Url
3.2 定位访问的类
3.3 执行Url所表示的方法
新闻热点
疑难解答