一:請求的過程
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時間,就可以使本連接持續的時間所產生的所有報文段都從網絡中消失。這樣就可以使下一個新的連接中不會出現這種舊的連接請求的報文段。