1. 程式人生 > >一次URL請求過程--tomcat

一次URL請求過程--tomcat

一:請求的過程

1.DNS域名解析

2.建立TCP連線(三次握手)

3.傳送請求--tomcat進行處理

4.四次揮手關閉連線 

二:詳解1---DNS域名解析

     1、瀏覽器會檢查快取中有沒有這個域名對應的解析過的IP地址,如果有,這個解析過程就結束。

     2、快取中沒有資料,瀏覽器會查詢作業系統快取中是否有這個域名對應的DNS解析結果。

     3、前兩個無法解析時,就要用到本地區的域名伺服器。它們一般都會快取域名解析結果。大約80%的域名解析到這裡就結束了,所以LDNS主要承擔了域名的解析工作。

     4、如果LDNS仍然沒有,就直接到Root Server域名伺服器請求解析。

     5、根域名伺服器返回給本地域名伺服器一個所查詢的主域名伺服器(gTLD Server)地址。

     6、本地域名伺服器LDNS再向上一步返回的gTLD伺服器傳送請求。

     7、主域名伺服器查詢並返回此域名對應的Name Server域名伺服器的地址,這個Name Server通常就是使用者註冊的域名伺服器。

     8、域名伺服器會查詢儲存的域名和IP的對映關係表,在正常情況下都根據域名得到目標IP地址,連同一個TTL值返回給LDNS Server域名伺服器。

     9、返回該域名對應的IP和TTL值,LDNS會快取這個域名和IP的對應關係,快取時間由TTL值控制。

     10、把解析的結果返回給使用者,使用者根據TTL值快取在本地系統快取中,域名解析過程結束。

 

三:詳解2---建立TCP連線

 建立TCP連線需要三次握手:建立一個TCP連線時,需要客戶端和服務端總共傳送3個包以確認連線的建立。在socket程式設計中,這一過程由客戶端執行connect來觸發,整個流程如下圖所示:

(1)第一次握手:Client將標誌位SYN置為1,隨機產生一個值seq=J,並將該資料包傳送給Server,Client進入SYN_SENT狀態,等待Server確認。(2)第二次握手:Server收到資料包後由標誌位SYN=1知道Client請求建立連線,Server將標誌位SYN和ACK都置為1,ack=J+1,隨機產生一個值seq=K,並將該資料包傳送給Client以確認連線請求,Server進入SYN_RCVD狀態。

(3)第三次握手:Client收到確認後,檢查ack是否為J+1,ACK是否為1,如果正確則將標誌位ACK置為1,ack=K+1,並將該資料包傳送給Server,Server檢查ack是否為K+1,ACK是否為1,如果正確則連線建立成功,Client和Server進入ESTABLISHED狀態,完成三次握手,隨後Client與Server之間可以開始傳輸資料了。

問題1:SYN攻擊

SYN攻擊就是Client在短時間內偽造大量不存在的IP地址,並向Server不斷地傳送SYN包,Server回覆確認包,並等待Client的確認,由於源地址是不存在的,因此,Server需要不斷重發直至超時,這些偽造的SYN包將長時間佔用未連線佇列,導致正常的SYN請求因為佇列滿而被丟棄,從而引起網路堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單,即當Server上有大量半連線狀態且源IP地址是隨機的,則可以斷定遭到SYN攻擊了。

使用如下命令可以讓之現行:netstat -nap | grep SYN_RECV

問題2:為什麼是三次握手

(a)若兩次握手,客戶端收到服務端的應答後進入ESTABLISHED(已建立連線狀態),而服務端在收到客戶端的連線請求之後就進入了ESTABLISHED狀態。如果出現網路擁塞,客戶端傳送的連線請求報文A過了很久沒有到達服務端,會超時重發請求報文B,服務端正確接受並確認應答,連線建立並開始通訊傳輸資料,等通訊結束之後釋放連線。此時,如果之前失效的連線請求A到達服務端,由於兩次握手就能成功建立連線,服務端收到請求A之後進入ESTABLISHED已建立連線狀態,等待發送資料或者主動傳送資料,此時,客戶端已經進入CLISED斷開連線狀態,伺服器會一直等下去,浪費伺服器連線資源。

(b)建立連線需要四次握手

         由於三次握手已經能確保建立可靠的連線,所以不需要四次或更多的握手。

第三次握手主要是為了防止已失效的請求報文段突然又傳送到了服務端而產生連線的誤判 

換種表述:為什麼要三次握手?不是一次,兩次或者四次。

我們來論證一下,如果只有一次會發生什麼情況,a向b發起連線請求,假設b沒收到,則b其實完全不知道a發起了請求,而a也完全不知道b收沒收到,所以一次握手是不可靠的;如果兩次握手呢,a向b發起連線請求,b收到a的請求給a回覆一個請求,假設此時a收到了b的回覆,a知道了b已經ready了,可b完全不知道a是否ready,有可能a並沒有收到b的請求,也有可能收到了,但這些b都完全不知道,所以只是單向的建立了連線;如果是四次握手呢,其實第2次讓a知道b ready了,第三次讓b知道a也ready了,第四次完全就是多餘了,會浪費網路資源。

 問題3:第三次握手失敗時發生什麼?

當第三次握手失敗時的處理操作,可以看出當失敗時伺服器並不會重傳ack報文,而是直接傳送RTS報文段,進入CLOSED狀態。這樣做的目的是為了防止SYN洪泛攻擊。

 四:詳解3---tomcat請求處理

     1. 請求被髮送到8080埠,被在那裡偵聽的Coyote HTTP/1.1 Connector獲得 。

     2. Connector把該請求交給它所在的Service的Engine來處理,並等待來自Engine的迴應 。

     3. Engine獲得請求,匹配它所擁有的所有虛擬主機Host (預設是localhost)

     4. localhost Host獲得請求,匹配它所擁有的所有Context

     5. Context獲得請求,在它的對映表中尋找對應的servlet

     6. 構造HttpServletRequest物件和HttpServletResponse物件,作為引數呼叫JspServlet的doGet或doPost方法

     7. Context把執行完了之後的HttpServletResponse物件返回給Host

     8. Host把HttpServletResponse物件返回給Engine

     9. Engine把HttpServletResponse物件返回給Connector

     10.Connector把HttpServletResponse物件返回給客戶browser

五:詳解四-----四次揮手

第一次揮手:TCP傳送一個FIN(結束),用來關閉客戶到服務端的連線。

第二次揮手:服務端收到這個FIN,他發回一個ACK(確認),確認收到序號為收到序號+1,和SYN一樣,一個FIN將佔用一個序號。

第三次揮手:服務端傳送一個FIN(結束)到客戶端,服務端關閉客戶端的連線。

第四次揮手:客戶端傳送ACK(確認)報文確認,並將確認的序號+1,這樣關閉完成。

問題1:那麼為什麼是4次揮手呢? 

      實際上兩邊連線完全可以分開看,用2次揮手斷開其中一邊連線,用另外2次揮手斷開另一邊的連線,最終完成整個連線關閉。之所以這樣設計,是因為有可能某一邊資料還未傳輸完,連線還未關閉。因為TCP被設計為全雙工協議,可以任何一邊單向傳送資料。

問題2:   tcp握手的時候為何ACK(確認)和SYN(建立連線)是一起傳送。揮手的時候為什麼是分開的時候傳送呢.

    因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能傳送FIN報文,因此不能一起傳送。故需要四步握手。

問題3: 為什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

第一,為了保證A傳送的最後一個ACK報文能夠到達B。這個ACK報文段有可能丟失,因而使處在LAST-ACK狀態的B收不到對已傳送的FIN+ACK報文段的確認。B會超時重傳這個FIN+ACK報文段,而A就能在2MSL時間內收到這個重傳的FIN+ACK報文段。如果A在TIME-WAIT狀態不等待一段時間,而是在傳送完ACK報文段後就立即釋放連線,就無法收到B重傳的FIN+ACK報文段,因而也不會再發送一次確認報文段。這樣,B就無法按照正常的步驟進入CLOSED狀態。 第二,A在傳送完ACK報文段後,再經過2MSL時間,就可以使本連線持續的時間所產生的所有報文段都從網路中消失。這樣就可以使下一個新的連線中不會出現這種舊的連線請求的報文段。