程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 【輪子狂魔】拋棄IIS,向天借個HttpListener,狂魔httplistener

【輪子狂魔】拋棄IIS,向天借個HttpListener,狂魔httplistener

編輯:C#入門知識

【輪子狂魔】拋棄IIS,向天借個HttpListener,狂魔httplistener


這一次我們要玩什麼?

 先聲明一下,由於這篇是基礎篇主要是通過這篇文章讓大家對使用HttpListener響應Http請求有個大概了解,所以正式的花樣輪子在下一篇推出,敬請期待 ^_^

 嗯哼,還有,我標題黨了一下,看完我這個系列的話,在特定場景下可拋棄IIS,但如果完全拋棄IIS就不要想咯 ^_^

 

 HttpListener:提供一個簡單的、可通過編程方式控制的 HTTP 協議偵聽器。(好吧,我承認這句是從MSDN上抄過來的)

 既然引子出來了,說明我們要開始玩Http請求了。

 那麼我們基礎篇要做的是,如何把一個 html 文件從服務器返回給客戶端。

 

一個Http請求我們需要做些什麼?

1.監聽一個地址前綴,如:http://localhost/

2.解析Url

3.執行Url所代表的指令

4.返回執行結果

 

監聽一個Http請求

 下面貼出的是主要的代碼,實際源碼中做了一些其他的處理,比如多線程防止界面卡死、HttpListener運行環境檢測、資源釋放、容錯等等。

1 HttpListener server = new HttpListener(); 2 try 3 { 4 MakeHttpPrefix(server); 5 server.Start(); 6 } 7 catch (Exception ex) 8 { 9 Logger.Exit("無法啟動服務器監聽,請檢查網絡環境。"); 10 } 11 12 IAsyncResult result = null; 13 while (!_terminated) 14 { 15 while (result == null || result.IsCompleted) 16 { 17 result = server.BeginGetContext(new AsyncCallback(ProcessHttpRequest), server); 18 } 19 _ready = true; 20 Thread.Sleep(10); 21 } 22 23 server.Stop(); 24 server.Abort(); 25 server.Close(); View Code

 

解析Url

解析Url時需要做幾個事情:

1.Url的長度限制

2.是否包含特殊字符

3.拆分指令與參數

1 /// <summary> 2 /// Url輔助類:對Url進行初步的解析 3 /// </summary> 4 public class UrlHelper 5 { 6 const int MAX_URI_LENGTH = 512; 7 string _scriptName = string.Empty; 8 CommandResult _parseResult = CommandResult.Success; 9 NameValueCollection _parameters = new NameValueCollection(); 10 char[] _uriInvalidChar = new char[] { '/', '\\' }; 11 char[] _pathInvalidChar = new char[] { '/', '\\', ':', '*', '?', '\"', '<', '>', '|' }; 12 public Uri _uri = null; 13 14 public string ScriptName 15 { 16 get { return _scriptName; } 17 } 18 19 public NameValueCollection Parameters 20 { 21 get { return _parameters; } 22 } 23 24 public CommandResult ParseResult 25 { 26 get { return _parseResult; } 27 } 28 29 public UrlHelper(Uri originalUri) 30 { 31 _uri = originalUri; 32 33 if (IsUriLengthError()) 34 { 35 return; 36 } 37 38 if (CheckPathAndQuery()) 39 { 40 ParsePathAndQuery(); 41 } 42 } 43 44 private bool IsUriLengthError() 45 { 46 if (_uri == null || _uri.ToString().Length > MAX_URI_LENGTH) 47 { 48 _parseResult = CommandResult.UrlTooLong; 49 return true; 50 } 51 return false; 52 } 53 54 private bool CheckPathAndQuery() 55 { 56 string pathAndQuery = _uri.PathAndQuery.Substring(1); 57 58 if (IsUrlInvalidChar(pathAndQuery)) 59 { 60 return false; 61 } 62 63 if (pathAndQuery.IndexOfAny(_uriInvalidChar) >= 0) 64 { 65 _parseResult = CommandResult.UrlInvalidChar; 66 return false; 67 } 68 else if (pathAndQuery.Length == 0) 69 { 70 _parseResult = CommandResult.NoExistsMethod; 71 return false; 72 } 73 74 string[] splitPathAndQuery = new string[] { }; 75 if (IsFileNameInvalidChar(pathAndQuery, splitPathAndQuery)) 76 { 77 return false; 78 } 79 80 return true; 81 82 } 83 84 private bool IsFileNameInvalidChar(string pathAndQuery, string[] splitPathAndQuery) 85 { 86 splitPathAndQuery = pathAndQuery.Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries); 87 if (splitPathAndQuery[0].IndexOfAny(_pathInvalidChar) >= 0) 88 { 89 _parseResult = CommandResult.FileNameInvalidChar; 90 return true; 91 } 92 return false; 93 } 94 95 private bool IsUrlInvalidChar(string pathAndQuery) 96 { 97 if (pathAndQuery.IndexOfAny(_uriInvalidChar) >= 0) 98 { 99 _parseResult = CommandResult.UrlInvalidChar; 100 return true; 101 } 102 return false; 103 } 104 105 private void ParsePathAndQuery() 106 { 107 string[] splitPathAndQuery = _uri.PathAndQuery.Substring(1).Split(new char[] { '?' }, StringSplitOptions.RemoveEmptyEntries); 108 SetScriptNameAndParameters(splitPathAndQuery); 109 } 110 111 private void SetScriptNameAndParameters(string[] splitPathAndQuery) 112 { 113 _scriptName = splitPathAndQuery[0]; 114 115 if (splitPathAndQuery.Length > 1) 116 { 117 _parameters = HttpUtility.ParseQueryString(splitPathAndQuery[1], Encoding.UTF8); 118 } 119 } 120 } View Code

 

執行Url所代表的指令和返回執行結果

1.判斷Url的請求文件後綴是否支持

2.檢索本地文件

3.如果文件存在則返回文件,不存在則返回異常(此處在後續擴展活增加更多可變性,比如一些動態執行方法等)

PS:由於此處代碼涉及幾個方法就不貼了,直接看源碼吧。(ProcessHttpRequest 方法)

 

有圖有真相

 請求一個簡單的Hello World的html文件,此處有個細節,就是浏覽器會發送ico請求。聰明的你如果想要顯示ico應該知道怎麼辦吧 ^_^

請求一個不支持的後綴,如:htm

 

下一次我們玩什麼?

1.豐富一下請求文件類型

2.支持執行方法的請求

3.在HttpListner裡玩一玩LUA腳本

 

最後,我要放源碼了 ^_^

http://git.oschina.net/doddgu/HttpListenerDemo

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved