如何從零寫一個http server?


以前整理過一個《從零開始學編程系列》justjavac/Programming-Alpha-To-Omega · GitHub

裡面收錄了從零開始寫編譯器、記事本、伺服器、操作系統、虛擬機、GC、資料庫、……

  • 從零開始寫個編譯器吧系列 (知乎專欄)
  • 從零開始寫一個簡單的操作系統 (伯樂在線)

  • 從零開始寫 JavaScript 框架 (圖靈社區)

  • 從零開始寫 jQuery 框架 (藍色理想 )

  • 從零開始 nodejs 系列文章 (粉絲日誌)

  • 從零開始編寫網路遊戲 ( 英特爾? 開發人員專區)

  • 從零開始編寫自己的 C# 框架 (博客園)

  • 如何從零開始寫一個 Chrome 擴展? (知乎)

  • 從零開始寫框架 (@jayli)

  • 「自己動手」系列

  • 一天時間用 Python 寫門語言 (justjavac博客)

  • 利用 Composer 一步一步構建自己的 PHP 框架 (歲寒博客 by JohnLui)

  • 自己動手寫虛擬機 (博客園)

  • 自己動手寫 HTTP Server #C (CSDN)

  • 自己動手寫 GC (Java譯站)

  • 自己動手寫一個推薦系統 #Python (博客園)

  • 自己動手寫壓縮軟體 #C++ (博客園)

  • 自己動手開發編譯器 (博客園)

  • 自己動手寫俄羅斯方塊 #C (51CTO)

  • 自己動手寫編輯器 #nodejs (@phodal)

  • 自己動手寫 Git HTTP Server #go (io-meter)

  • 使用 Symfony2 的組件創建自己的 PHP 框架 (@ruchengtang)

  • 資料庫的最簡單實現 (阮一峰)

  • 動手寫一個C語言編譯器 (伯樂在線)

  • 自己動手寫 Basic 解釋器 (CSDN)


考慮到從0開始的0指代不明,我想還是跳過OS及網卡驅動之類的玩意,從socket這個1開始。

1.建立一個TCP Socket伺服器。

首先編寫一個TCP Socket伺服器,是因為HTTP通信是建立在TCP Socket基礎上的。所要做的工作就是監聽某個指定埠(默認HTTP服務在80),接收訪問請求並建立連接,接收發來的流,並且提供回複流的能力。這一步可以簡單可以複雜,可以考慮並發、均衡、埠連接限制balabala,也可以二逼到啥都不管。總之我們需要監聽一個埠就是了。

2.編寫一個解析HTTP Request的解析器。

既然是HTTP服務,從之前監聽的埠收來的流里自然就是HTTP Request。Request分表頭和正文,包括訪問地址、UA、Cookie等各類參數以及提交的表單等內容。詳細格式看看HTTP協議文檔就好。

3.實現URL路由。

獲得了Request之後,我們知道用戶訪問了個什麼地址,就要指向相應的內容。根據地址來指定內容的工作就是路由,把不同的路徑交給不同的程序(函數、腳本…)處理。

4.產生Response。

HTTP Response其實與Request很類似,也是區分表頭和正文,多幾個關機字表示當前相應狀態、響應內容類型之類的東西。正文里就是你需要的回應,可能是個json,可能是個靜態文件,也可能是別的什麼東西。從路由處得到響應的內容,然後按照HTTP Response的要求包起來。最後經過之前的Socket服務返回給用戶。

基本上簡單的HTTP Server就這麼點東西,可以說並不複雜。但是考慮到各種額外功能,例如許可權、ip過濾、並發/非同步、request轉發、websocket、https…其實還是蠻麻煩的。


sudo nc -kl 80

等請求來了,在終端裏手打響應頭和內容。



python -m SimpleHTTPServer


mini_httpd

mini_httpd 是基於多進程模式的 http server,不是很適合嵌入應用程序, 假如要嵌入自身應用,可以考慮 mongoose

https://github.com/cesanta/mongoose

以前還沒有怎麼用github的時候自己寫了一個,這個東西其實不難寫,作為寫socket程序練手的很合適,寫了以後你對於tcp server 的一些基本要領,簡單的內存管理,字元串處理等等都會很熟悉了。 而且http server 作為一般伺服器程序的一些介面單元,調試介面也很合適很方便。

騷年,動手吧! 會物有所值的!


從0開始的話,首先要掌握必要的網路知識,可以去讀 → TCP/IP詳解 卷1:協議 (豆瓣) 的對應部分。

實現的話可以讀一下這個的代碼 → Tiny HTTPd | SourceForge.net,不到五百行,通俗易懂。

希望有幫助。


如果題主有python和http原理的基礎知識,建議直接閱讀python的SimpleHttpServer源碼。

模塊實現了一個簡單但標準的Http Server,內部的注釋和文檔很詳細,並且代碼設計的也相當規範,很適合新手閱讀學習。


CSAPP 裡面有個很簡單的Tiny web server

Tiny擼完你可以看看 cesanta/mongoose · GitHub

最後,Nginx在山頂等著你,如果你一直繼續往上爬的話


import java.io.*;
import java.net.*;
public class ServerDemo {
public static void main(String args[]) throws IOException {
ServerSocket ss = new ServerSocket(12345);//埠號12345
while(true) {
Socket socket = ss.accept();
OutputStream out = socket.getOutputStream();
BufferedReader br = new BufferedReader(new FileReader("D:\this.html"));
out.write("HTTP/1.0 200
".getBytes());
out.write("Content-Type: text/html
".getBytes());
out.write("
".getBytes());
String line=null;
while((line = br.readLine()) != null) {
out.write(line.getBytes());
}
socket.close();
br.close();
out.close();
}
}
}


其實Web伺服器這個東西,是個非常簡單而有趣的東西,首先你要明白HTTP協議是建立在TCP/IP協議基礎上的,其次你需要了解請求報文和響應報文的結構,了解了以上兩點,你只需要在服務端開一個Socket,然後循環監聽客戶端連接,每次根據客戶端請求進行處理然後按照規範將信息返回給客戶端就可以啦!

下面向題主推薦我使用C#純手工打磨HTTP伺服器的心得,目前實現了Get和Post以及靜態頁面解析,希望對題主的學習有幫助:

http://qinyuanpei.com/2016/06/11/make-a-http-server-with-csharp-01.html

http://qinyuanpei.com/2016/06/11/make-a-http-server-with-csharp-02.html

http://qinyuanpei.com/2016/06/11/make-a-http-server-with-csharp-03.html

整個系列共有5篇,現在寫到第4篇,等寫完整個系列以後再回來更新答案,總之我想說寫個HTTP伺服器真的沒有那麼難~(≧▽≦)/~


給我的文章打個小廣告,從TCP開始寫HTTP Server Esimorp - 知乎

新的文章發布在專欄裡面啦~ 知乎專欄


Akagi201/libuv-webserver · GitHub

前段時間用C寫了一個, 用的非同步libuv實現, http解析用了輕量級高性能的http-parser, 推薦新手看.


讀一下linux manual的bind, socket, listen, accept的頁面,讀一下RFC的文檔,開始寫,完。

反正我們都是這麼乾的。

然後如果能夠看著這個步驟完成的話,一般的項目已經難不倒你了。


自己擼過一個webserver.當時還自己YY了一個動態腳本語言。有演示視頻,有文檔。有興趣可交流

https://github.com/whiletest/webserver


可以在github上看一個開源項目tinyhttp,看完大致原理就會懂了,對你寫也會有很大幫助。


看BOA的源碼


推薦閱讀:

網路評論員是激化了還是緩解了輿論矛盾?
學習網路工程的女生後來都怎樣了?
如何系統地做計算機網路實驗?
ipv4可用的公網ip個數是多少?如何計算得來的?
IT圈子裡,銷售對工程師的總體看法是怎樣?

TAG:計算機網路 | HTTP |