目錄
- 介紹
- Web Server在Web架構系統中的作用
- Web Server與Web網站程式的互動
- HTTPListener與Socket兩種方式的差異
- 附帶Demo原始碼概述
- Demo效果截圖
- 總結
介紹
本篇文章主要介紹使用HTTPListener型別自己動手建立一個Web Server,建立的Web Server能夠接收來自瀏覽器端的HTTP請求,並且能夠傳遞給對應的Web站點進行處理,最後將處理結果(Html或者其他格式)返回給瀏覽器。
博主前面曾經介紹過使用Socket模擬Web Server的執行過程、Socket模擬瀏覽器傳送HTTP請求過程。分別參見:
本篇文章並沒有使用Socket去實現,而是使用另外一種封裝程度更高、更抽象的System.Net.HTTPListener型別實現。
Web Server在Web架構系統中的作用
Web Server在一個B/S架構系統中起到的作用不僅多而且相當重要,Web開發者大部分時候並不需要了解它的詳細工作機制。雖然不同的Web Server可能功能並不完全一樣,但是以下三個功能幾乎是所有Web Server必須具備的:
- 接收來自瀏覽器端的HTTP請求
- 將請求轉發給指定Web站點程式(後者由Web開發者編寫,負責處理請求)
- 向瀏覽器傳送請求處理結果
下圖顯示Web Server在整個Web架構系統中所處的重要位置:
如上圖,Web Server起到了一個“承上啟下”的作用(雖然並沒有“上下”之分),它負責連線使用者和Web站點。
我們可以看到,Web Server預設情況下需要與Web開發者編寫的Web網站程式“通訊”(圖中假設三個網站均在一個Web Server上),那麼這裡怎麼處理呢?實時上,任何Web開發者在使用某個平臺開發Web程式時,必須遵守某些“規則”,比如使用到某些框架等。遵守了這些規則,開發出來的網站就可以放到Web Server上,這是不是有點像“程式擴充套件”的意思?
Web Server與Web網站程式的互動
每個網站就像一個個“外掛”,只要網站開發過程中遵循了Web Server提出的規則,那麼該網站就可以“插”在Web Server上,我們便可以通過瀏覽器訪問網站。
理論上講,每個Web Server均是一個宿主,而每個網站均是一個外掛(plug-in)。Web Server主要負責通訊等功能,網站程式主要負責資料處理。
至於“宿主”怎樣與“外掛”通訊,請參見博主前面的一篇文章“應用程式擴充套件”。
由於每個Web Server均能持續接收HTTP請求,因此每個Web Server中均應該存在一個類似下圖所示的迴圈結構:
如上圖,為了提高Web Server接收HTTP請求的效率,圖中虛線框一般採用非同步處理,請求處理過程不會影響整個迴圈。
HTTPListener與Socket兩種方式的差異
事實上,HTTP協議是應用層協議。資料在傳輸層上依然是採用TCP進行傳輸的,因此,自己動手採用Socket方式完全能夠模擬出Web Server的工作過程(正如文章開頭講到的)。博主前面有一篇部落格講述“使用Socket請求Web Server”,其實就是使用Socket來模擬瀏覽器的通訊行為。在.NET中的System.Net名稱空間中,包含一些更高層次、更抽象的型別也可以完成對瀏覽器的模擬,如System.Net.HTTPWebRequest和System.Net.HTTPWebResponse等型別,至於它們和直接使用Socket有什麼區別,請參見下表:
分類 |
Web Server端 |
瀏覽器端 |
優點 |
缺點 |
Socket方式 |
Socket.Accept: 負責接收瀏覽器端的Socket連線請求
Socket.Receive: 負責接收瀏覽器傳送的資料
Socket.Send: 負責向瀏覽器傳送資料 |
Socket.Connect: 負責向Web Server傳送連線請求
Socket.Receive: 負責接收Web Server發來的回覆
Socket.Send: 負責向Web Server傳送請求 |
更底層,靈活性更強 |
更底層,需要充分了解HTTP協議、TCP/IP協議 |
System.Net名稱空間中的型別 |
HTTPListener.GetContext: 負責接收瀏覽器端的HTTP請求
HTTPListenerRequest: 該類負責接收瀏覽器端的請求(Request)資料
HTTPListenerResponse: 該類負責向瀏覽器傳送回覆(Response)資料 |
HTTPWebRequest: 該類負責向Web Server傳送HTTP請求
HTTPWebResponse: 該類負責接收來自Web Server發來的回覆 |
更高層級別的抽象,不需要過多的瞭解HTTP、TCP等通訊知識 |
更抽象,用法固定(不過需要的都已經包含) |
可以看到,以上兩種方式最終達到的效果其實是一樣的。
注:請區分HTTPWebRequest與Asp.NET中的HTTPRequest。後者只能用在Asp.NET中,屬於Asp.NET中的核心物件。同理請區分HTTPWebResponse與Asp.NET中的HTTPResponse。它們的名稱空間分別為:System.NET和System.Web。
附帶Demo原始碼概述
原始碼包含三個專案,分別為:
- HTTPServer:模擬的一個Web Server(不足70行程式碼)
- HTTPUtility:一個抽象層,專門為了Web Server與網站程式之間的互動。這裡充分應用了“依賴倒置原則(DIP)”,目的就是降低Web Server與網站程式之間的耦合度。
- MyWebsite:一個(模擬的)網站程式,需要依賴HTTPUtility。
如果將Demo中的三塊與現實一一類比,那麼HTTPServer便是IIS/Apache,HTTPUtility便是我們開發Web程式時需要使用到的框架/原則,MyWebsite便是我們開發出來的Web網站程式。
將編譯之後的MyWebsite專案DLL檔案拷貝到HTTPServer可執行程式同一目錄下的web資料夾中即可(類似一個網站釋出的過程)。開啟HTTPServer.exe檔案執行,即可在瀏覽器中訪問MyWebsite網站。
原始碼中註釋比較詳細,在此就不多說原始碼的事情。
Demo效果截圖
總結
兩種方式實現的過程、程式碼結構均類似。主要掌握兩點:
- Web Server中的迴圈結構(泵),負責持續接收請求
- Web Server與網站程式(Plug-in)之間的互動
作為一個Web開發者,瞭解這些幾乎用不到的知識也是必需的。
原始碼下載:http://files.cnblogs.com/xiaozhi_5638/HTTP_Web_Server.rar
轉發請保留原文連結地址。