歡迎光臨
每天分享高質量文章

一起寫一個Web伺服器(1)

有天一個女士出門散步,路過一個建築工地,看到三個男人在幹活。她問第一個男人,“你在乾什麼呢?”,第一個男人被問得很煩,咆哮道,“你沒看到我在碼磚嗎?”。她對回答不滿意,然後問第二個男人他在乾什麼。第二個男人回答,“我正在砌牆”,然後轉移註意力到第一個男人,他說,“嘿,你碼過頭了,你要把最後一塊磚拿掉。”。她還是對回答不滿意,然後問第三個男人在乾什麼。第三個男人仰望著天空對她說,“我正在建造世界上最大的教堂。”。當他站在那裡仰望天空的時候,另外兩個男人開始爭論磚位置不對的問題。第三個男人轉向前兩個男人說,“嘿,夥計們,別擔心那塊磚了,那是裡面的牆,它會被灰泥堵塞起來,然後沒人會看到那塊磚。去另一層幹活吧。“

故事的寓意是說,當你瞭解整個系統,理解不同的部分如何組織到一起的(磚,牆,教堂),你就能找出問題並快速解決之(磚位置不對)。

這跟從零開始搭建你的WEB伺服器有什麼關係呢?

我相信,要成為優秀的開發者,你必須對你每天都用的底層的軟體系統有進一步的理解,包括程式語言、編譯器和直譯器、資料庫和作業系統、WEB伺服器和WEB框架。為了更好更深入的理解這些系統,你必須從零開始一塊磚地,一面牆地,重建它們。

子曰:聞之我也野,視之我也饒,行之我也明

”我看過的,我還記得。“

”我做過的,我都理解了。“

(子曰,聞之我也野,視之我也饒,行之我也明)

此時我希望你能夠相信,從重建不同的軟體系統來開始來學習它們是如何工作的,是一個好主意。

在這個由3部分組成的系列文章中,我會向你展示怎樣搭建一個基本的WEB伺服器。咱們開始吧。

重中之重,什麼是WEB伺服器?

簡而言之,它是一個位於一個物理伺服器上的網路伺服器(呀,伺服器上的伺服器),它等待客戶端傳送請求。當它接收到一個請求,就會生成一個響應並回發給客戶端。客戶端和伺服器使用HTTP協議通訊。客戶端可以是瀏覽器或者別的使用HTTP協議的軟體。

一個非常簡單的WEB伺服器實現長什麼樣呢?以下是我寫的一個。例子是用Python語言寫的,但是即使你不會Python(它是一個非常易學的語言,試試!),你仍然可以透過程式碼和下麵的解釋理解相關概念:

import socket

HOST, PORT = ”, 8888

listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

listen_socket.bind((HOST, PORT))

listen_socket.listen(1)

print ‘Serving HTTP on port %s …’ % PORT

while True:

client_connection, client_address = listen_socket.accept()

request = client_connection.recv(1024)

print request

http_response = “””

HTTP/1.1 200 OK

Hello, World!

“””

client_connection.sendall(http_response)

client_connection.close()

把上面的程式碼儲存到webserver1.py或者直接從GitHub下載,然後像下麵這樣在命令列執行它

$ python webserver1.py

Serving HTTP on port 8888 …

現在在你的WEB瀏覽器位址列裡輸入以下URL http://localhost:8888/hello,敲回車,見證奇跡的時刻。你會看到瀏覽器顯示”Hello, World!“,像這樣:

認真做一下吧,我會等你的。

做完了?很好。現在我們討論一下它到底怎麼工作的。

首先我們從你剛才鍵入的WEB地址開始。它叫URL,這是它的基本結構:

這個就表示怎樣告訴瀏覽器要查詢和連線的WEB伺服器地址,和你要獲取的伺服器上的頁面(路徑)。但是在瀏覽器傳送HTTP請求前,瀏覽器需要先和WEB伺服器建立TCP連線。然後瀏覽器在TCP連線上傳送HTTP請求,然後等待伺服器回發HTTP響應。當瀏覽器接收到響應後,顯示響應,在本次例子中,瀏覽器顯示“Hello, World!”。

我們再詳細探索一下客戶端和伺服器在傳送HTTP請求和響應前如何建立TCP連線的。在建立連線,它們必須使用所謂的sockets。用你命令列下的telnet手動模擬瀏覽器吧,而不是直接使用瀏覽器。

在執行WEB伺服器的同一臺電腦上,在命令列啟動一個telnet會話,指定連線到localhost主機,連線埠為8888,然後按回車:

$ telnet localhost 8888

Trying 127.0.0.1 …

Connected to localhost.

此時,你已經和執行在你本地主機的伺服器建立了TCP連線,已經準備好傳送並接收HTTP訊息了。下圖中你可以看到一個伺服器要經過的標準步驟,然後才能接受新的TCP連線。

在同一個telnet會話中,輸入 GET /hello HTTP/1.1然後敲回車:

$ telnet localhost 8888

Trying 127.0.0.1 …

Connected to localhost.

GET /hello HTTP/1.1

HTTP/1.1 200 OK

Hello, World!

你完成了手動模擬瀏覽器!你發送了一個HTTP請求並得到了一個HTTP響應。這是HTTP請求的基本結構:

HTTP請求由行組成。行指示了HTTP方法(GET,因為我們請求我們的伺服器傳回給我們一些東西)、代表我們想要的伺服器上的“頁面”的路徑 /hello和協議版本。

為了簡單起見,此時我們的WEB伺服器完全忽略了上面的請求行。你也可以輸入任何垃圾字元取代“GET /hello HTTP/1.1”,你仍然會得到“Hello, World!”響應。

一旦你輸入了請求行,敲了回車,客戶端就傳送請求給伺服器,伺服器讀取請求行,打印出來然後傳回相應的HTTP響應。

以下是伺服器回發給客戶端(這個例子中是telnet)的HTTP響應:

咱們分析一下它,響應包含了狀態行HTTP/1.1 200 OK,隨後一個必須的空行,和HTTP響應body。

響應狀態行TTP/1.1 200 OK包含了HTTP版本,HTTP狀態碼和HTTP狀態碼理由短語OK。瀏覽器得到響應時,它就顯示響應的body,所以你就看到了“Hello, World!”

這就是WEB瀏覽器怎麼工作的基本模型。總結來說:WEB伺服器建立一個監聽socket然後開始迴圈接受新連線。客戶端初始化一個TCP連線,在連線成功後,客戶端傳送HTTP請求到伺服器,伺服器響應一個顯示給使用者的HTTP響應。客戶端和伺服器都使用socket建立TCP連線。

你現在你擁有了一個非常基礎的WEB伺服器,你可以用瀏覽器或其他的HTTP客戶端測試它。正如你看到的,使用telnet手動輸入HTTP請求,你也就成了一個人肉HTTP客戶端。

對你來說有一個問題:“怎樣在你的剛完成的WEB伺服器下執行Django application、Flask application和Pyramid application?在不單獨修改伺服器來適應這些不同的WEB框架的情況下。”

我會在本系列的第2部分秀給你看的。繼續收看。

順便說下,我在寫一本書 “一起構建WEB伺服器:第一步”,它解釋了從零開始寫一個基本的WEB伺服器,還更詳細的講解了我上面提到的話題。訂閱郵件組來獲取關於書籍和釋出時間和最近更新。

靈感來自於Lead with a Story: A Guide to Crafting Business Narratives That Captivate, Convince, and Inspire

原文出處:ruslanspivak.com

譯文出處:伯樂線上 – 秣馬兒

連結:http://web.jobbole.com/82360/



贊(0)

分享創造快樂