當前位置:
首頁 > 最新 > Django:瀏覽器訪問伺服器的過程

Django:瀏覽器訪問伺服器的過程

用戶通過瀏覽器瀏覽網站的過程:

用戶瀏覽器(socket客戶端)

客戶端往服務端發消息

客戶端接收消息

關閉

網站伺服器(socket服務端)

啟動,監聽

等待客戶端連接

服務端收消息

服務端回消息

關閉(一般都不會關閉)

下面,我們先寫一個服務端程序,來模擬瀏覽器伺服器訪問過程。

你會發現,運行程序之後並且用瀏覽器訪問 127.0.0.1:8001 ,程序會報錯,瀏覽器顯示「該網頁無法正常運作」,如下圖

為什麼呢?這時候就要引出HTTP 協議了。


HTTP協議

HTTP是一個客戶端終端(用戶)和伺服器端(網站)請求和應答的標準(TCP)。

HTTP請求/響應步驟:

1. 客戶端連接到Web伺服器

一個HTTP客戶端,通常是瀏覽器,與Web伺服器的HTTP埠(默認為80)建立一個TCP套接字連接。

2. 發送HTTP請求

通過TCP套接字,客戶端向Web伺服器發送一個文本的請求報文,一個請求報文由請求行、請求頭部、空行和請求數據4部分組成。

3. 伺服器接受請求並返回HTTP響應

Web伺服器解析請求,定位請求資源。伺服器將資源複本寫到TCP套接字,由客戶端讀取。一個響應由狀態行、響應頭部、空行和響應數據4部分組成。

4. 釋放連接TCP連接

若connection 模式為close,則伺服器主動關閉TCP連接,客戶端被動關閉連接,釋放TCP連接;若connection 模式為keepalive,則該連接會保持一段時間,在該時間內可以繼續接收請求;

5. 客戶端瀏覽器解析HTML內容

客戶端瀏覽器首先解析狀態行,查看錶明請求是否成功的狀態代碼。然後解析每一個響應頭,響應頭告知以下為若干位元組的HTML文檔和文檔的字符集。客戶端瀏覽器讀取響應數據HTML,根據HTML的語法對其進行格式化,並在瀏覽器窗口中顯示。

瀏覽器和服務端通信都要遵循一個HTTP協議(消息的格式要求)

關於HTTP協議:

1. 瀏覽器往服務端發的叫 請求(request)

請求的消息格式:

請求方法 路徑 HTTP/1.1

k1:v1

k2:v2


請求數據

2. 服務端往瀏覽器發的叫 響應(response)

響應的消息格式:

HTTP/1.1 狀態碼 狀態描述符

k1:v1

k2:v2


響應正文

HTTP請求報文格式:

HTTP響應報文格式:

再回到我們剛才的程序,程序報錯的原因是接收到了瀏覽器的訪問報文請求,但是我們的伺服器程序在響應的時候並沒有按照HTTP響應格式(一個響應由狀態行、響應頭部、空行和響應數據4部分組成)進行回應,所以瀏覽器在處理伺服器的響應的時候就會出錯。

因此,我們要在發送給瀏覽器的響應中按照HTTP響應格式加上 狀態行、響應頭部、空行和響應數據 這四部分。

這時候,在瀏覽器上面就可以看到正確的頁面了,並且可以調出Chrome的開發者工具查看到我們傳過來的HTTP響應格式。


根據不同的路徑返回不同的內容

細心的你可能會發現,現在無論我們輸出什麼樣的路徑,只要保持 IP 和埠號不變,瀏覽器頁面顯示的都是同樣的內容,這不太符合我們日常的使用場景。

如果我想根據不同的路徑返回不同的內容,應該怎麼辦呢?

這時候就需要我們把伺服器收到的請求報文進行解析,讀取到其中的訪問路徑。

觀察收到的HTTP請求,會發現,它們的請求行、請求頭部、請求數據是以
進行分隔的,所以我們可以根據
對收到的請求進行分隔,取出我們想要的訪問路徑。

這時候,我們訪問不同的路徑,例如 http://127.0.0.1:8001/yimi/ http://127.0.0.1:8001/xiaohei/ 會在瀏覽器上顯示不一樣的內容

可以看到,我們現在的程序邏輯不是很清晰,我們可以改一下,url 用一個列表存起來,url 對應的響應分別寫成一個個函數,通過函數調用進行 url 訪問,你會發現,這跟某個框架的處理方式很像很像(偷笑罒ω罒~~~)


返回具體的 HTML 頁面

現在,你可能會在想,目前我們想要返回的內容是通過函數進行返回的,返回的都是一些簡單地位元組,如果我想要返回一個已經寫好的精美的 HTML 頁面應該怎麼辦呢?

我們可以把寫好的 HTML 頁面以二進位的形式讀取進來,返回給瀏覽器,瀏覽器再進行解析,這就可以啦!


返回動態 HTML 頁面

這時候,你可能又會納悶,現在返回的都是些靜態的、固定的 HTML 頁面,如果我想返回一個動態的 HTML 頁面,應該怎麼辦?

動態的網頁,本質上都是字元串的替換,字元串替換髮生服務端,替換完再返回給瀏覽器。

這裡,我們通過返回一個當前時間,來模擬動態 HTML 頁面的返回過程。

可以看到,現在我們每一次訪問 yimi 頁面,都會返回一個當前時間。


小結一下

1. web 框架的本質:

socket 服務端 與 瀏覽器的通信

2. socket 服務端功能劃分:

a. 負責與瀏覽器收發消息( socket 通信) --> wsgiref/uWsgi/gunicorn...

b. 根據用戶訪問不同的路徑執行不同的函數

c. 從 HTML 讀取出內容,並且完成字元串的替換 --> jinja2 (模板語言)

3. Python 中 Web 框架的分類:

1. 按上面三個功能劃分:

1. 框架自帶 a,b,c --> Tornado

2. 框架自帶 b 和 c,使用第三方的 a -->Django

3. 框架自帶 b,使用第三方的 a 和 c --> Flask

2. 按另一個維度來劃分:

1. Django --> 大而全(你做一個網站能用到的它都有)

2. 其他 --> Flask 輕量級


引入 wsgiref 模塊實現 socket 通信

不知道你會不會覺得之前的程序中,socket 通信特別麻煩,而且還都是一樣的套路,完完全全可以獨立出來做成一個模塊,要用的時候再直接引進來用就可以了。

沒錯,有你這種想法的人還不在少數(吃鯨......),特別是一些大牛們,就 socket 通信這一塊,做出了一些特別好用的模塊,例如我們下面要用的 wsgiref 模塊。

你會發現,使用了 wsgiref 模塊之後,程序封裝更好了,代碼邏輯也更加清晰了。


WSGI 協議

經過上面的 wsgiref 模塊的示例,在使用通信模塊的方便之餘,你可能已經意識到一個問題,類似於 wsgiref 這樣的模塊肯定不止一個,我們自己寫的 url 處理函數需要和這些模塊進行通信,那麼,我怎麼知道這些模塊傳過來的信息是什麼格式?如果各個模塊傳過來的信息結構都不一樣的話,那豈不是說我得根據每一個模塊去定製它專門的 url 處理函數?這不科學,這中間肯定需要一個協議進行約束,這個協議,就叫WSGI 協議

作者:守護窗明守護愛

源自:

http://www.cnblogs.com/chuangming/p/9072251.html


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 python 的精彩文章:

Python愛好者周知:Scikit-Learn中文文檔正式發布
處理異常—Python 基礎

TAG:python |