日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

看问题要看到本质:从Web服务器说起

發布時間:2025/3/21 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 看问题要看到本质:从Web服务器说起 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是個很長的故事, 讓我們從Web服務器來開始。

Web服務器是個挺簡單的東西,工作很簡單,在80端口上監聽,解析客戶端發過來的HTTP的請求, 然后把相對應的HTML文件、Image等返回給客戶端就可以了。?像這樣:

?

這就是一個靜態內容服務器,所謂靜態內容,就是服務器端的內容如HTML不會變化,每次請求都是一樣的。除非人們手工改了它。

實現這樣一個“玩具Web服務器”并不難,只要能了解服務器端Socket編程就可以了, 主要工作是編程處理HTTP協議的細節。

動態內容

但是如果想再往前走一步,讓Web服務器能產生動態內容,那就難了。

比如說來了一個HTTP請求,在其中攜帶者用戶名和密碼,要求你去數據庫做一個查詢,看看用戶是否存在。

POST ?/login

user=xxxx&pwd=xxx

這個靜態的Web服務器就搞不定了,它根本,也不應該去查詢數據庫。

怎么辦呢?你可以用某種語言(比如C語言)寫個程序, 來查詢數據庫,假設這個程序的名字叫db-query。

可是你將面對非常棘手的問題:??Web服務器是個進程,db-query也是個進程,這倆貨之間怎么通信呢?

(友情提示,下面內容略顯枯燥,可跳過)

首先是參數的傳遞,一種辦法是這樣:對于每個動態請求,Web服務器進程創建一個db-query的子進程,然后通過環境變量把參數傳遞過去。

web服務器:

setenv("QUERY_STRING","user=xxxx&pwd=xxx")

db-query子進程 :

param = getenv("QUERY_STRING")。

下一個問題:db-query這個子進程獲得了用戶名和密碼,查詢了數據庫,怎么把查詢結果返回給瀏覽器?

有個很巧妙的辦法!

每個程序都有所謂的標準輸出(STDOUT),db-query只要調用printf這個函數,數據就會輸出到STDOUT,我們就可以在黑乎乎的控制臺上看到了數據輸出了。

但是輸出到控制臺是萬萬不行的,我們得輸出到socket才可以發回瀏覽器。

每個瀏覽器和服務器的連接都是一個Socket, 每個socket都有一個文件描述符fd, 如果把查詢數據庫程序db-query的STDOUT重定向到那個fd,會發生什么?

沒錯!db-query的所有輸出都直接發送的客戶端的socket了,Web服務器可以撒手不管了!

當然,如果瀏覽器要看到的是HTML頁面, 那db-query這個程序就需要輸出HTML了。

?

這種方式就就是大名鼎鼎的CGI,當你看到網址中有cgi-bin字樣的時候,很有可能就是用CGI實現的。? 只要遵循CGI協議, 可以用任何語言來實現動態的網站。

這是人類邁出的一大步,有了這一步,才能在網上購物,辦公,社交,聊天...... ?你才能看到我這篇文章(嗯,也許騰訊把微信公眾號的文章都靜態化了, 請了解詳情的同學告知)

但是,CGI是非常復雜和笨拙的, 主要體現在:

第一,對每個請求,都得創建一個子進程去執行,這是個非常大的開銷。

第二,對程序員來說,編程極為痛苦,要操作環境變量,還需要直接在編程語言中輸出HTML!

麻煩不麻煩,難受不難受,上個世紀的程序員苦逼不苦逼?

?

Servlet

怎么才能跳出苦海?必須得做到關注點的分離!

程序員的關注點是:拿到Http 請求中的數據,執行業務, 然后輸出Http 響應。?別的什么環境變量,重定向,別來煩我!

那就簡單了,讓程序員寫個類,里邊是業務邏輯, 然后我們想辦法構建一個HttpRequest對象和HttpResponse對象,傳遞給程序員的類讓他使用不就行了?

誰來創建這個HttpRequest和Response 對象, ?然后調用程序員寫的類?

靜態Web服務器表示我不愿意,我就想管好我這一畝三分地,把靜態內容給大家服務好。

Tomcat已經迫不及待地要上場了,我來我來。碼農朋友們,我送給你們一個規范,叫Servlet, 你們按照Servlet的規范來寫程序,放到我這里運行,別的什么都不用管了。

程序員很高興,只需要寫簡單的Servlet就行了,HttpRequest和HttpResponse對象由Tomcat來創建,可以從HttpRequest中獲得Header, Cookie, QueryString 等信息, 從HttpResponse中獲得輸出流,直接向瀏覽器輸出結果, 簡單又直接。

?

Tomcat還鄭重向大家聲明:對于每個請求,我只會用一個線程來出來,線程的開銷可比進程小多了。

對于那個在代碼中混雜HTML的問題怎么處理?

?Tomcat也有辦法, 可以在HTML混雜代碼!這就是JSP。執行期其實會被編譯成Servlet。

(碼農翻身注:請移步《JSP:一個裝配工的沒落》)

你看,責任分離了,每個人只要辦好自己的事情就好。

(注:實際上,我們不會在Servlet中寫業務邏輯, Servlet現在通常是一個通往框架的入口。)

WSGI

CGI表示不服:遵循我的協議,任何語言都可以來實現動態網站,你Servlet只是Java規范,不管別的語言了?

Servlet規范確實沒法跨語言實現,那要是Python也想做動態Web網站,該怎么辦?

既然已經認識到動態網站的本質了, 可以采用類似的思想來處理嘛!?我們為Python也定義一個規范,叫做WSGI?(Web Service Gateway Interface)。

讓程序員寫個類或者函數(稱為wsgi application),在其中實現邏輯。讓某個動態服務器(稱為wsgi server)把Http Request和Response傳遞給它,就可以執行了。

但是Python表示:我不喜歡你們Java 那一套啰里啰嗦的類,HttpRequest 不就是一些key value嗎?放到我鐘愛的dict中多好 !我把它叫做enviroment, HttpResponse也沒必要,直接用函數的返回值(確切說是一個可迭代對象)就好。

看看,是不是和Java 的Servlet 很像?(當然,忽略了很多細節。)

從本質上來說,都是為了關注點的分離:

1. 用一個動態內容服務器(wsgi server,Tomcat等)來接受并且封裝HTTP 請求,降低程序員的負擔。

2. 程序員只需要遵循約定(servlet,wsgi)就可以輕松實現自己的業務,不用關注系統的處理細節。

如果你先學的Java,通過Servlet理解了動態內容網站的本質和解決問題思路,再看到Python的wsgi,一眼就能看透,學起來飛快,反過來也是如此。

Web服務器的例子還比較簡單,但是也體現出了這個道理:遇到問題要深度思考,努力看到本質,這樣才能舉一反三。

總結

以上是生活随笔為你收集整理的看问题要看到本质:从Web服务器说起的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。