1. 程式人生 > >http請求從瀏覽器到伺服器過程

http請求從瀏覽器到伺服器過程

前些天剛看完《How Tomcat Works》,雖然書比較老,但是看完後收穫還是挺多的,懂得了tomcat的內部結構和一個請求進出tomcat的全過程。前些天看的為什麼現在提呢,因為做到了面試題呀,發現自己原本很清晰的思路突然模糊了,所以花點時間總結一下。
題目是說一說在瀏覽器中輸入一個url後,直到瀏覽器顯示頁面的過程中發生了什麼?
如果我說的話,會分四步:
1.通過訪問的域名找出其IP地址
2.TCP/TP三次握手
3.進入tomcat後如何處理的
4.TCP/IP四次揮手(如果需要的話)
一、第一步:
客戶端先檢查本地是否有對應的IP地址,若找到則返回響應的IP地址。若沒找到則請求上級DNS伺服器,直至找到或到根節點。(瀏覽器快取→系統快取→路由器快取→ISP DNS快取→從根域名伺服器遞迴搜尋)
二、第二步:
傳送端先發送一個帶有SYN(synchronize)標誌的資料包給接收端,在一定的延遲時間內等待接收的回覆。接收端收到資料包後,傳回一個帶有SYN/ACK標誌的資料包以示傳達確認資訊。接收方收到後再發送一個帶有ACK標誌的資料包給接收端以示握手成功。在這個過程中,如果傳送端在規定延遲時間內沒有收到回覆則預設接收方沒有收到請求,而再次傳送,直到收到回覆為止。
這裡寫圖片描述

建立連線成功後,瀏覽器給web伺服器傳送一個HTTP請求。
第三步:
這裡我先說一下自己理解tomcat的內部處理過程:
在HttpllProcessor的process方法裡,會先從socket裡讀取http請求資料,並解析請求頭,構造Request物件和Response物件,然後呼叫Adapter.service()方法。Adapter.service()完成請求行以及請求體的解析,並把解析出來的資訊封裝到Request和Response物件中,Adapter(確切說是org.apache.catalina.connector.CoyoteAdapter)是connector和container的橋樑,經過這一步,請求就從connector傳遞到container裡了,Adapter.service()方法之後便將封裝了Request以及Response物件的Socket傳給Container容器了。到了Container,Container容器是子容器的父介面,所有的子容器都必須實現這個介面。在Tomcat中Container容器的設計是典型的責任鏈設計模式,其有四個子容器:Engine、Host、Context和Wrapper。這四個容器之間是父子關係,Engine容器包含Host,Host包含Context,Context包含Wrapper。Engine容器處理請求呼叫了StandardEngineValve的invoke方法。在StandardEngineValve的invoke方法中,選擇可用的Host容器處理當前的請求,選擇Host容器後,就呼叫其invoke方法,所以具體的處理就轉移到了Host容器。在Host容器的invoke中,為特定的請求URL選擇一個Context容器。Context容器是一個Web專案的代表,主要管理Servlet例項,在Tomcat中Servlet例項是以Wrapper出現的。在StandardContextValve的invoke()方法中,做了這幾件事:
1.禁止直接訪問WEB-INF或者META-INF目錄下的資源
2.選擇具體的Wrapper處理請求
3.返回一個確認響應
4.呼叫Wrapper容器的invoke方法,把處理請求交給StandardWrapperValve處理。
Wrapper容器負責管理一個Servlet,包括Servlet的裝載、初始化、資源回收。Wrapper是最底層的容器,其不能在新增子容器了。Wrapper是一個介面,其標準實現類是StandardWrapper。呼叫loadServlet的allocate方法的時候呼叫了StandardWrapperValve的invoke方法,在Wrapper容器獲得請求後,通過allocate方法從例項池棧中彈出一個servlet例項來處理這個請求,servlet例項被封裝成filterChain物件,緊接著通過一系列的過濾器過濾到達servlet.service()方法。之後發生的過程就是我們熟悉的request獲取引數並用response進行響應的過程了。這裡主要是本人的一些理解過程,方便自己以後回顧的,讀者看不懂也沒關係,如果能讀懂的話,下面的過程便是十分簡單的。下面給出正常的思路:
假設來自客戶的請求為:
http://localhost:8080/wsota/wsota_index.jsp

1) 請求被髮送到本機埠8080,被在那裡偵聽的Coyote HTTP/1.1 Connector獲得
2) Connector把該請求交給它所在的Service的Engine來處理,並等待來自Engine的迴應
3) Engine獲得請求localhost/wsota/wsota_index.jsp,匹配它所擁有的所有虛擬主機Host
4) Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的預設主機)
5) localhost Host獲得請求/wsota/wsota_index.jsp,匹配它所擁有的所有Context
6) Host匹配到路徑為/wsota的Context(如果匹配不到就把該請求交給路徑名為””的Context去處理)
7) path=”/wsota”的Context獲得請求/wsota_index.jsp,在它的mapping table中尋找對應的servlet
8) Context匹配到URL PATTERN為*.jsp的servlet,對應於JspServlet類
9) 構造HttpServletRequest物件和HttpServletResponse物件,作為引數呼叫JspServlet的doGet或doPost方法
10)Context把執行完了之後的HttpServletResponse物件返回給Host
11)Host把HttpServletResponse物件返回給Engine
12)Engine把HttpServletResponse物件返回給Connector
13)Connector把HttpServletResponse物件返回給客戶browser
第四步:
這裡寫圖片描述

所謂四次揮手就是終止TCP連線,斷開一個TCP連線需要客戶端和服務端傳送四次資料包以確定斷開連線。
1.Client傳送一個數據包,用來關閉Client到server的資料傳輸,Client進入最後的等待狀態。
2.server接到資料包經過判斷後,傳送確認資訊給Client,自己進入等待關閉狀態。
3.server傳送一個數據包給Client,用來關閉server到Client的資料傳輸
4.Client接收到資料經過判斷後,自己進入Time_wait狀態,server接收資料經過判斷無誤後,server進入關閉狀態,Client等待2MLS(Maxmum segment lifetime),它是任何報文在網路丟棄前在網路內的最長時間,過了這個時間,Client就自動關閉了。
最後解釋一下圖中字母縮寫的含義:
SYN:同步訊號(Synchronize)
ACK:確認字元(Acknowledge Character)
RST:重連位(Reset)
FIN:對方終止傳送資料(Finally)(對方沒有資料再發送給你啦)
好相信知道這麼多,再面http請求應該不慌了。