標籤:http os ar java strong 檔案 資料 sp 問題
其實普通web應用,實際上就是對http的應用,http是一種基於TCP協議的網路傳輸協議,工作在應用程式層,作為web開發人員,我主要從http的角度來看待這個問題:
首先,對於http肯定是有用戶端和伺服器的,在這個語境中,用戶端和伺服器本質上也都是一個軟體,實現了http協議相關標準的軟體。用戶端一般由都是由瀏覽器充當,也就是說,在瀏覽器中實現了http用戶端的相關功能。而伺服器的實現就多種多樣啦,我們可以用java寫servlet,c#寫ASP.net,還有php,ruby,Python,nodejs等。實際上我想,http服務在作業系統底層應該有實現,而這些語言只不過是利用作業系統的http服務封裝成自己的介面供開發人員編寫web伺服器程式。而我們熟悉的IIS,Tomcat,Apache,Web logic,都是能夠作為某些web伺服器容器的大型伺服器平台,它們都會包括很多更為強大的功能。一般來說,我們這裡所說的伺服器指的是自己用特定語言寫的web應用伺服器程式。nodejs不需要web容器,本身就有對http的直接應用模組,所以用nodejs建立一個web伺服器是很方便的。
整體通訊
有了用戶端和伺服器,就可以開始通訊了,整體上分為3個步驟:
- 因為http是構建在TCP之上,那麼自然是要經過3次握手建立串連。
- 建立串連後,伺服器會根據url請求中的資訊進行處理,作出響應,一般來說是找到一個html檔案返回給用戶端。
- 用戶端即瀏覽器得到html,進行渲染。
下面詳細說下這3個步驟
建立串連
這個跟網路關聯多一些,我網路學的馬馬虎虎,只能大體說一下。對於http的用戶端,它的輸入就是一個url,而對於建立串連,它需要的只是url的host(主機)部分,而主機地址一般是網站的網域名稱,所以第一步肯定是是網域名稱解析,也就是要通過DNS伺服器進行網域名稱解析得到網站的ip地址,然後向這個ip地址發送一個串連建立的請求,如果伺服器接收到請求會返回一個確認,用戶端得到確認再次發送確認,串連建立成功。當然在這個過程中還會涉及到很多細節,這是網路中的知識,在這裡不多講。
伺服器處理
建立好串連後,用戶端就會發送http請求,請求資訊包含一個頭部和一個請求體,
一般的web技術都會把請求進行封裝然後交給我們的伺服器進行處理,比如servlet會把請求封裝成httpservletrequest對象,把響應封裝成httpsevletresponse對象。nodejs的http模組,當你建立伺服器的時候會寫一個回呼函數,回調的參數用來接受http請求對象和響應對象,然後在回呼函數中對請求進行處理。
在請求對象中我們可以得到path(路徑),queryString(查詢字串),body(post請求中提交的資料)等。對請求的處理就可以很複雜,也可以很簡單。我們可以根據path找到用戶端想要的檔案,讀取這個檔案,然後通過響應對象把內容返回給用戶端,這個過程,不同的技術提供的api可能不同,尤其是用慣了MVC架構的人,可能只是指定一個檔案,或者在設定檔中設定一下就好了。但是最終的實現肯定是符合http響應標準的,也就是要有一個回應標頭和一個響應體。我一般接觸到的設定回應標頭就是設定content-type來決定MIME類型,設定Cache-Control,last-modify等緩衝內容。一般來說返回給用戶端的內容是一個html字串,然後content-type設為text/html。當然也可能用戶端請求的是一個image檔案,那麼就是讀取image檔案後,content-type可能設為image/png,image/jpg等,然後把內容返回給用戶端。這樣一次對請求的處理就結束了。
當然這個過程太單一,而且處理過程也可能很複雜,又有資料的操作,又有頁面的構建,又有路徑的尋找匹配,又有檔案的讀取等等,於是就出現了MVC架構以及後來演變出的各種MV*架構。這裡不細講MVC的內容,因為需要很長的篇幅。只是概述一下MVC主要做了什麼,在我看來最重要的就是解耦和模組化。我認為MVC實現最重要的有兩點:
- 路由匹配,http請求的path中就不需要指定到具體的視圖位置,而是按照我們制定的規則進行匹配,這樣就有了很大的靈活性,可程式化性。
- 模板技術,一般來說我們最後返回給用戶端的是一個html字串,而有時候這個字串往往不是靜態單一的,有的時候需要和資料進行結合,需要拼接。這就帶來了很大的麻煩,模板技術為解決這個問題帶來很大的便利性,同時又能夠把視圖和資料進行解耦。
用戶端渲染
用戶端接收到伺服器傳來的響應對象,從中得到html字串和MIME,根據MIME知道了要用頁面渲染引擎來處理內容即html字串,於是進入頁面渲染階段,這又是一個很龐雜的體系。我只能大體上說一下:
從瀏覽器的角度講,它包含幾大組件,網路功能(比如http的實現)算是其中之一,渲染引擎也是其中之一,還有其它的一些比如自己UI介面,javascript解譯器,用戶端資料存放區等等。在這裡我們主要關注渲染引擎和javascript解譯器,對於web開發人員來說,這才是瀏覽器的核心。
我們能夠在瀏覽器中看到一個頁面,那麼這個頁面是怎麼出現的呢?實際上就是調用底層繪圖API給畫出來的。不同的渲染引擎,它的實現也不同,主流的引擎包括IE的Trident,chrome和safary的webkit,firefox的Gecko,chrome又出了一個Blink,放棄webkit。於是乎才有了讓人頭疼的各種相容性問題。
整體上頁面渲染的過程大致是這樣的:
渲染引擎得到html字串作為輸入,然後對html進行轉換,轉化成能夠被DOM處理的形式,接著轉換成一個dom樹,在解析html的過程,解析到<link>,<script>,<img>等一些請求標籤時,會發送請求把對應的內容擷取到。這時又會同步進行css的解析,構建出css樣式規則應用到dom樹上,然後進行一定的布局處理,比如標記節點塊在瀏覽器中的座標等形成最終的渲染樹,最後根據這棵渲染樹在瀏覽器視窗中進行繪製。
最終我們就看到了頁面的樣子。
當然在頁面渲染過程中還會同步進行javascript的解析,而且這兩者是在同一個線程中的,所以一旦javascript死迴圈,頁面的渲染也就進行不下去了。
以上是我從一個web開發人員的角度思考的整個過程。如果從別的角度更細化的去想,還包括許多內容:
比如整個網路通訊中協議的封裝:
在本機中,把要傳輸的內容即請求對象在應用程式層上加上App首部,傳遞到傳輸層加上TCP首部,到網路層加上IP首部,資料連結層加上乙太網路的首部和尾部,然後轉換成bit流進入網路環境中。到達主機後在一層層解鎖裝,最後把內容交給伺服器程式。
再比如這個過程中的認證,加密,安全,編碼等問題都會有一定的處理,不過這些內容我就不是很瞭解。
瀏覽器輸入url到整個頁面顯示出來經曆的過程