天天看點

HTTP-點開浏覽器輸入網址背後發生的那點事

前言

Internet最早來源于美國國防部ARPANet,1969年投入運作,到現在已有很長一段路了,各位想要了解發展史可以百度下,這裡就不多說了。

現如今當我們想要擷取一些資料,首先是打開某個浏覽器,在位址欄輸入位址,想要的資訊出現在你的面前。

大家有沒有想過輸入位址就能傳回給你想要的資訊是怎麼實作的呢?

下面就來簡單說下它的實作流程,不過在這之前先來了解下HTTP基本概念如下

HTTP基本概念

在這引用 http://www.zsythink.net/archives/76

這是一篇為初學者準備的文章,是以作者會盡量從基礎出發,盡量細緻的描述每一個細節,以求讓初學者不會一頭霧水,有一定基礎的同學就不用看了,以免浪費你的時間。

假設部落客今天春心蕩漾,想要通路一些不可描述的小網站,于是,部落客悄悄的打開了浏覽器,在浏覽器的位址欄中輸入了一個小網站的網址,

此處假設這個小網站的網址為 www.zsythink.net ,當部落客輸入了這個網址以後,浏覽器中就顯示了部落客想要看到的内容,整個過程如下圖所示。

HTTP-點開浏覽器輸入網址背後發生的那點事

那麼,浏覽器傳回給我們的内容是怎麼産生的呢?

這些内容肯定不是憑空産生的,而是有人為我們準備了這些内容,當我們在浏覽器的位址欄中輸入網址以後,

這些提前準備好的内容即可傳回到浏覽器中,以便有需要的人能夠檢視到這些内容,

而檢視這些内容的人就是我們平常所說的"客戶",客戶往往會通過"用戶端程式"去請求、檢視這些内容,

我們最常使用的用戶端程式就是浏覽器了,是以,在之後的http相關的文章中,

如果沒有特别說明,我們所說的"用戶端"就是指"浏覽器",我們使用用戶端去檢視我們想要的内容,

而提供内容的一端被稱為"服務端",當作為客戶時,我們需要在電腦上安裝用戶端軟體(即浏覽器),

通過用戶端軟體檢視我們想要的内容,而作為提供内容的人,也需要在服務端的計算機上安裝對應的軟體,

才能為我們提供服務,而服務端的計算機就是我們常說的"伺服器",安裝在伺服器上的、為我們提供内容的軟體被稱之為"web伺服器軟體"。

是以,綜上所述,我們可以了解到如下名詞

注:如下名詞的解釋均針對http而言,在後面的文章中我們會解釋什麼是http,此處不用糾結

用戶端:用戶端通常是指浏覽器,比如谷歌浏覽器、火狐浏覽器、IE等,浏覽器安裝在客戶使用的電腦上,是以,在描述http時,用戶端通常也代指那些安裝了浏覽器的電腦。

服務端:服務端通常是指那些安裝了"web服務軟體"的計算機,這些服務端的計算機被稱為伺服器。

沒錯,聰明如你一定想到了,說白了,用戶端與服務端就是兩台電腦,分别安裝了不同的軟體,服務端提供内容,用戶端檢視内容。

HTTP-點開浏覽器輸入網址背後發生的那點事

是以,當我們通路網頁時,大緻的過程如下圖所示。

HTTP-點開浏覽器輸入網址背後發生的那點事

用戶端與服務端既然能夠通訊,那麼證明它們之間一定是通過某種方法進行溝通的,就像你我之間能夠進行溝通一樣。

舉例說明

你和我都說漢語,是以,當我說"蘋果"這個詞的時候,你就會想到一種水果,或者想到一個手機品牌,

但是當我對一個美國人說"蘋果"兩個字時,他可能并不能了解我在說什麼,因為他可能聽不懂漢語,

如果我想要對他表達"蘋果"這個詞,我需要說"Apple",他才會明白我說的是什麼,當我跟你聊天時,我們都說漢語,

當兩個美國人聊天時,他們都說英語,這樣,才能有效的溝通,總之,如果想要能夠順暢的溝通,

溝通雙方都必須遵守相同的協定,我們可以把漢語了解成一種協定,把英語也了解成一種協定,

隻要溝通雙方都遵守相同的協定,雙方就能夠順暢的溝通,隻要溝通雙方都遵守相同的協定,雙方就能夠了解對方想要做什麼。

當然,之是以拿漢語、英語舉例,是為了讓初學者能夠更加容易的了解"協定"這個詞,但是請不要錯誤的以為"協定"就是"語言",

之是以拿語言舉例,是為了友善了解,說白了,"協定"可以了解為某種規則或者某種約定,

隻要大家都嚴格按照這種約定行事,世界就會正常的運轉,比如"紅燈停,綠燈行"也可以了解為一種協定,

比如在馬路上都要靠右行駛(在中國),也是一種協定,比如在小飯館,你給老闆人民币,老闆給你對應的餐食,

也是一種協定,"協定"的概念稍微有一些抽象,稍微有一些寬泛,此處大概有一個印象即可,在學習的過程中,我們自己就會慢慢的了解它了。

用戶端與服務端之間,也需要遵守某些相同的協定,才能夠順暢的通訊,細心如你一定注意到了,我說的是"某些"協定,也就是說,雙方要遵守的協定不止有一種,它們需要同時遵守多種協定,才能夠正常的完成整個通訊過程。

比如http協定,剛才已經說過,不同的"層面"中,需要使用不同的協定,http協定就是應用層的一種協定,http協定是什麼意思呢?

http是HyperText Transfer Protocol的縮寫,HyperText Transfer Protocol譯為"超文本傳輸協定"。

從字面上了解,這種協定是用來傳輸"超文本"的,我們可以暫且粗暴的将"超文本"了解成我們所謂的"網頁"(這樣并不準确,但是友善了解),那麼,我們可以将http協定了解為一種"網頁傳輸協定"。

一次完整的HTTP請求過程

web服務請求處理步驟

HTTP-點開浏覽器輸入網址背後發生的那點事

HTTP服務通信過程

HTTP-點開浏覽器輸入網址背後發生的那點事

人性化HTTP請求相應圖

HTTP-點開浏覽器輸入網址背後發生的那點事

圖檔來自:

了解Http請求與響應

大緻如下

域名解析 --> TCP3次握手 --> 發起http請求 --> 伺服器響應http請求并傳輸資料 –>  浏覽器解析并渲染呈現給使用者 –> TCP4次揮手

域名解析

當使用者在浏覽器輸入

https://www.cnblogs.com/時

,浏覽器會對此域名或主機進行解析,得到對應的IP位址,那麼它時怎麼進行域名解析的呢?

1、首先先去本機hosts檔案查找此FQDN沒有沒定義的指向所在的IP位址條目,如果找到,就結束解析

2、如果沒有找到,回去浏覽器器本身DNS緩存裡去尋找,找打結束解析

3、沒有找到,會去本機配置的首選DNS伺服器查詢,一般這是三大營運商提供的,通過UTP53端口發起請求,這個請求是遞歸查詢,DNS伺服器收到請求後,會查詢自身緩存,找到條目并且沒有過期,就傳回給使用者,結束解析。如果沒有找到,它會去找根伺服器,全球13個根伺服器(根伺服器位址本機DNS伺服器内置),詢問根伺服器(你知不知道一個域名叫“www.cnblogs.com”的IP位址),根回複說,(我不知道此域名的IP位址,但我知道com域的IP位址,你去詢問它吧),于是運作商提供的DNS伺服器就去詢問com這個域,(你知不知道一個叫“www.cnblogs.com”域名IP位址),com域回答你說,(我不知道此域名的IP位址,但我知道“cnblogs.com域的IP位址,你去問他吧“),這是運作商DNS伺服器,對cnblogs.com域發起請求詢問,(你知不知道一個叫”www.cnblogs.com“域的IP位址,它一查,發現此域,就是它負責的,就會對你說,此域是我負責的,它的IP是X.X.X.X這時運作商DNS伺服器拿到位址,就會傳回客戶主機核心,核心再傳回給浏覽器,到此解析結束,進行下一步。

當然這裡面還要涉及到IP –> MAC(實體位址)的解析

TCP3次握手

浏覽器拿到域名對應的IP後,會拿一個随機端口向WEB服務程式80端口發起TCP請求連結

HTTP-點開浏覽器輸入網址背後發生的那點事

備注:

SYN(synchronous建立聯機)

ACK(acknowledgement 确認)

PSH(push傳送)

FIN(finish結束)

RST(reset重置)

URG(urgent緊急)

Sequence number(順序号碼)

Acknowledge number(确認号碼)

舉例

A : 你好我是A,你能聽得到我說話嗎?

B : 聽到了,我是B,你能聽到我說話嗎?

A : 可以,聽到了

好建立連接配接,開始聊天!

過程

第一次握手:建立連接配接,用戶端将SYN标記為1,seq标記為x,并将SYN包發送到伺服器,并進入SYN_SEND狀态,等待伺服器确認;

第二次握手:伺服器收到SYN,知道用戶端要建立連結,同時向用戶端也發送一個SYN包(SYN=1)和一個ACK包(ACK=1),随機産生一個數seq=y,ack=x+1(用戶端的seq值x加1),來确認用戶端的SYN,并進入SYN_RECV;

第三次握手:用戶端收到伺服器發來的SYN+ACK後,确認ack值,并回複伺服器端一個ACK确認,發送完畢後,雙方進入ESTABLISHED狀态。

三次握手成功後,開始傳輸資料。

一個完整的三次握手也就是 請求---應答---再次确認

連結建立成功後,就要開始下一步,傳輸資料

HTTP請求相應處理

1、建立TCP連接配接:

接收或拒絕連接配接請求

發送請求封包

HTTP-點開浏覽器輸入網址背後發生的那點事

2、接收請求:

接收用戶端發來的請求封包中的資訊對某資源的一次請求的過程

Web通路響應模型(Web I/O)

1)單程序I/O模型:

啟動一個程序處理使用者請求,而且一次隻處理一個,多個請求被串行響應

2)多程序I/O模型:

并行啟動多個程序,每個程序響應一個連接配接請求

3)複用I/O結構:

啟動一個程序,同時響應N個連接配接請求

實作方法:    多線程模型和事件驅動

      多線程模型: 一個程序生成N個線程,每線程響應一個連接配接請求

      事件驅動:    一個程序處理N個請求

4)複用的多程序I/O模型:

啟動M個程序,每個程序響應N個連接配接請求,同時接收M*N個請求

3、處理請求:

伺服器對請求封包進行解析,并擷取請求的資源及請求方法等相關資訊,根據方法,資源,首部和可選的主體部分對請求進行處理

HTTP-點開浏覽器輸入網址背後發生的那點事

HTTP常用請求方式,Method

GET、POST、HEAD、PUT、DELETE、TRACE、OPTIONS

4、通路資源:

伺服器擷取請求封包中請求的資源web伺服器,即存放了web資源的伺服器,負責向請求者提供對方請求的靜态資源,或動态運作後生成的資源

資源放在服務端特定的目錄下

備注:通過MAC位址和端口号确定具體的應用程式

5、建構響應封包:

一旦Web伺服器識别除了資源,就執行請求方法中描述的動作,并傳回響應封包。響應封包中 包含有響應狀态碼、響應首部,如果生成了響應主體的話,還包括響應主體

HTTP-點開浏覽器輸入網址背後發生的那點事

6、發送響應封包

向用戶端回複封包

7、記錄日志:

最後,當事務結束時,Web伺服器會在日志檔案中添加一個條目,來描述已執行的事務

備注:這中間還要涉及到https的建立過程

資料傳輸完畢就要斷開連結了

四次揮手

如圖

HTTP-點開浏覽器輸入網址背後發生的那點事

資料傳輸完畢後,雙方都可釋放連接配接。最開始的時候,用戶端和伺服器都是處于ESTABLISHED狀态,然後用戶端主動關閉,伺服器被動關閉。

  1. 用戶端程序發出連接配接釋放封包,并且停止發送資料。釋放資料封包首部,FIN=1,其序列号為seq=u(等于前面已經傳送過來的資料的最後一個位元組的序号加1),此時,用戶端進入FIN-WAIT-1(終止等待1)狀态。 TCP規定,FIN封包段即使不攜帶資料,也要消耗一個序号。
  2. 伺服器收到連接配接釋放封包,發出确認封包,ACK=1,ack=u+1,并且帶上自己的序列号seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀态。TCP伺服器通知高層的應用程序,用戶端向伺服器的方向就釋放了,這時候處于半關閉狀态,即用戶端已經沒有資料要發送了,但是伺服器若發送資料,用戶端依然要接受。這個狀态還要持續一段時間,也就是整個CLOSE-WAIT狀态持續的時間。
  3. 用戶端收到伺服器的确認請求後,此時,用戶端就進入FIN-WAIT-2(終止等待2)狀态,等待伺服器發送連接配接釋放封包(在這之前還需要接受伺服器發送的最後的資料)。
  4. 伺服器将最後的資料發送完畢後,就向用戶端發送連接配接釋放封包,FIN=1,ack=u+1,由于在半關閉狀态,伺服器很可能又發送了一些資料,假定此時的序列号為seq=w,此時,伺服器就進入了LAST-ACK(最後确認)狀态,等待用戶端的确認。
  5. 用戶端收到伺服器的連接配接釋放封包後,必須發出确認,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此時,用戶端就進入了TIME-WAIT(時間等待)狀态。注意此時TCP連接配接還沒有釋放,必須經過(最長封包段壽命)的時間後當用戶端撤銷相應的TCB後,才進入CLOSED狀态。
  6. 伺服器隻要收到了用戶端發出的确認,立即進入CLOSED狀态。同樣,撤銷TCB後,就結束了這次的TCP連接配接。可以看到,伺服器結束TCP連接配接的時間要比用戶端早一些。

問題1-為什麼連接配接的時候是三次握手,關閉的時候卻是四次握手?

答:

因為當Server端收到Client端的SYN連接配接請求封包後,可以直接發送SYN+ACK封包。其中ACK封包是用來應答的,

SYN封包是用來同步的。但是關閉連接配接時,當Server端收到FIN封包時,很可能并不會立即關閉SOCKET,

是以隻能先回複一個ACK封包,告訴Client端,"你發的FIN封包我收到了"。隻有等到我Server端所有的封包都發送完了,

我才能發送FIN封包,是以不能一起發送。故需要四步握手。

問題2-為什麼要三次握手

為了防止已失效的連接配接請求封包段突然又傳送到了服務端,因而産生錯誤。

網上轉載的例子不錯:

三次握手:

A:“喂,你聽得到嗎?”A->SYN_SEND

B:“我聽得到呀,你聽得到我嗎?”應答與請求同時發出 B->SYN_RCVD | A->ESTABLISHED

A:“我能聽到你,今天balabala……”B->ESTABLISHED

四次揮手:

A:“喂,我不說了。”A->FIN_WAIT1

B:“我知道了。等下,上一句還沒說完。Balabala…..”B->CLOSE_WAIT | A->FIN_WAIT2

B:”好了,說完了,我也不說了。”B->LAST_ACK

A:”我知道了。”A->TIME_WAIT | B->CLOSED

A等待2MSL,保證B收到了消息,否則重說一次”我知道了”,A->CLOSED

參考連結

1、

2、

https://blog.csdn.net/qzcsu/article/details/72861891

3、

https://zhuanlan.zhihu.com/p/21940234

4、

https://www.jianshu.com/p/c1d6a294d3c0?from=jiantop.com

繼續閱讀