這跟安裝NoteJs程序運行腳本文件搭建一個簡單Http服務器一樣,相比起來,它的優點是可以開發的應用是免安裝,跨平臺的,放在移動盤上便捷的,這里著重講http服務器實現的過程,以便自主實現特定的功能和服務。
打開Visual Studio開發工具,創建一個項目,
注意,項目開發語言是C#,使用的Net framework 4+ 框架,
創建的項目可以是以下三種
- Console 控制臺
- WinForm 桌面程序
- WPF 桌面程序
新建項目
這里以最簡單的Console控制臺項目開發為例,
新建項目,選一個項目來創建:控制臺應用(.NET Framework),如下圖
編寫代碼
創建好一個項目后,在第一個代碼Program.cs文件中,
獲取本機IP
添加如下代碼如下,先獲取本機的IP列表
using System.Net;namespace ConsoleApp1
{class Program{static void Main(string[] args){var IPs = Dns.GetHostEntry(Dns.GetHostName()).AddressList.Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork && ip.ToString().EndsWith(".1") != true).Select(ip => ip.ToString()).ToList();//...}}
}
繼續寫,獲取第一個IP
var IP = IPs.FirstOrDefault();
啟用HTTP服務
接下來,實現一個Http服務器
var server = new HttpListener();
var url = $"http://{IP}:8080/";
server.Prefixes.Add(url);
server.Start();
Console.WriteLine("Http服務器已開啟,用瀏覽器訪問:" + url);
從上面代碼中可看出,先傳入IP和端口號,就可開啟一個Http服務
被拒絕訪問
可以試著編譯運行看,能否正常運行,
此時運行可會出現一個錯誤提示:拒絕訪問!
這就是觸及到網絡安全和權限問題了,有三種解決方案:
解決方案一
將IP換成’127.0.0.1’
缺點:只能本機訪問
解決方案二
以管理員身份運行程序
缺點:每次運行前都要授權:確認以管理員身份
解決方案三
在訪問控制規則中設置,
以管理員身份運行Shell終端(CMD),執行一條命令如下:
netsh http add urlacl url=http://{ip}:{port}/ user=Everyone
其中{ip}:{port} 換成自己的IP和端口號
這樣,下次運行程序就不會再次彈出拒絕訪問問題,
若想恢復,就執行一條命令,如下:
netsh http delete urlacl url=http://{ip}:{port}/
訪問首頁
那http服務器順利開啟后,
若要訪問頁面,那是看不到什么頁面內容的,
處理請求
需要自己實現,添加一行代碼如下
server.BeginGetContext((ar) => OnResult(server, ar), null);
從上面代碼看,當請求訪問它的時候,會調用那一個方法OnResult
實現那個方法OnResult,代碼如下
private static void OnResult(HttpListener server, IAsyncResult ar)
{if (!server.IsListening) return;var context = server.EndGetContext(ar);var request = context.Request;var response = context.Response;var method = request.HttpMethod.ToUpper();//...待實現if (server.IsListening) server.BeginGetContext((ar2)=>OnResult(server, ar2), null);
}
從上面代碼看,對寫過后端服務代碼的同學來說,就會覺得這很像服務器處理請求業務的邏輯
- request 是處理請求的對象
- response 是響應輸出的對象
- method 是請求方法
在待實現那里,繼續添加代碼,
先判斷請求地址,添加代碼如下
var absUrl = HttpUtility.UrlDecode(request.Url.AbsolutePath);//request.RawUrl
if (absUrl=="/" || absUrl=="/index.html"){//...
}
從上面代碼看,判斷到地址是請求加載首頁的話,就去加載首頁文件
加載文件
把寫好的網頁文件index.html
放到運行程序文件對應的文件夾wwwroot
下,
然后實現,讀取本地文件內容,代碼如下
var filePath = System.IO.Path.Combine(Environment.CurrentDirectory, "wwwroot", "index.html");
var contents = System.IO.File.ReadAllText(filePath);
//...
響應內容
讀取到內容,將輸出給瀏覽器,代碼如下
response.ContentType = "text/html;charset=UTF-8";
response.AddHeader("Content-Type", "text/html");
using (var writer = new System.IO.StreamWriter(response.OutputStream))
{writer.Write(contents);
}
其中
text/html
,是表示文件內容類型,
注意,以上響應輸出方法只能處理符合條件text/*
內容類型的文件,
其它文件類型的文件,需要另外的方法來實現處理請求響應,
輸出完成后,記得執行如下代碼,關閉響應
response.Close();
內容類型
網頁文件中還有加載的資源文件是比較常見的,它們的內容類型不一樣,如下表:
名稱 | 文件后綴名 | 內容類型 |
---|---|---|
文本 | .txt | text/plain |
網頁 | .html | text/html |
網頁 | .htm | text/html |
樣式 | .css | text/css |
數據 | .json | application/json |
腳本 | .js | application/x-javascript |
字體 | .ttf | application/x-font-ttf |
圖標 | .ico | image/x-icon |
圖片 | .jpg | image/jpeg |
圖片 | .jpeg | image/jpeg |
更多文件內容類型,這里就不多列舉了,如有需要請自行搜索
訪問請求數據
當瀏覽器訪問網頁后,網頁中有個資源標簽需要加載服務器資源文件,還有網頁腳本會請求訪問服務器的數據,
所有加載資源的請求方法通常是GET,
判斷請求方法
在之前的請求處理中,通過以下代碼能判斷
var method = request.HttpMethod.ToUpper();
if (method=="GET") {//...
} else if (method=="POST") {//...
}
處理GET請求
其中GET請求這里就不展開講,這實現很簡單吧,之前將加載網頁文件就是處理GET請求來的,
有的請求地址中會帶上查詢數據,同如下這樣
http://…com/q?csdn=zs1028
可判斷請求地址中的查詢部分,代碼如下
var query = request.QueryString;
//...
判斷請求地址里的查詢數據,再處理不同的請求響應
處理POST請求
是POST請求的話,通常會發來表單數據,
在請求處理中可以讀取表單數據,代碼如下:
// 檢查是否為 multipart/form-data
if (!request.ContentType.StartsWith("multipart/form-data", StringComparison.OrdinalIgnoreCase))
{throw new Exception("Only multipart/form-data is supported");
}var parser = new MultipartFormDataParser(request.InputStream);
//...
其中
HttpMultipartParser
是使用Nuget包管理器安裝的,當時是 2.1.7版本,
表單數據就在parser
對象里,看里面有什么屬性,
例如,前端頁面操作上傳的文件,在請求處理中可從parser
對象的屬性Files
獲取
處理請求響應
處理完請求后,需要響應數據,
如果是返回文本內容,就執行以下代碼
response.AddHeader("Content-Type", "text/plain");var contents = "ok";
using (var writer = new System.IO.StreamWriter(response.OutputStream))
{writer.Write(contents);
}
如果返回JSON內容,就執行以下代碼
var result = new { code = 0, errMsg = "ok" };
response.AddHeader("Content-Type", "application/json");
var contents = new JavaScriptSerializer().Serialize(result);
using (var writer = new System.IO.StreamWriter(response.OutputStream))
{writer.Write(contents);
}
從代碼中看出,
result
就是object
對象類型,可以轉換成json序列化數據
寫到這里,基本上就可以編譯運行測試了,
一個簡單HTTP服務器就這樣實現處理,是不是感覺很容易,它的應用場景可以多了,請自由想象!
對前端開發來說,可以把前端項目生成的網頁打包進一個程序中,輕松部署,再加上瀏覽器運行組件那就是跨平臺的程序。
就寫到這里,( _ )/~~拜拜