-
HTTP請求的完整過程:
域名解析---->與服務器建立連接---->發起HTTP請求------>服務器響應HTTP請求,瀏覽器得到HTML代碼-->瀏覽器解析HTML代碼,並請求HTML代碼中的資源(如js、css、圖片)---->瀏覽器對頁面進行渲染呈現給用戶
- 域名解析
- 瀏覽器會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鐘,智能容納1000條緩存-Chrome瀏覽器),看緩存中是否有對應條目,有且沒有過期解析到此結束,否則執行②
- 如果瀏覽器自身的緩存裏沒有找到對應的條目,那麼瀏覽器會搜索操作系統自身的DNS緩存,如果找到且沒過期則解析到此結束,否則執行③
- 如果操作系統DNS緩存也沒有找到,那麼嘗試讀取hosts文件,看這個文件裏是否有該域名對應的IP地址,如果有則解析成功,否則執行④
- 如果在hosts文件中也沒有找到對應的條目,瀏覽器就會發起一個DNS的系統調用,就會向本地配置的首選DNS服務器(一般是電信運營商提供的)發起域名解析請求,(通過的UDP協議向DNS53端口發起請求,這個請求是遞歸的請求,也就是運營商的DNS服務器必須得提供給我們該域名的IP地址),運營商的DNS服務器首先找自身緩存,找到對應條目且沒有過期則解析成功。如果沒有找到對應的條目,則有運營商的DNS代我們的瀏覽器發起迭代DNS解析請求,它首先是會找根域的DNS的IP地址(這個DNS服務器內置13臺根域名的DNS的IP地址),找到根域名的DNS地址發起請求,根域發現這是一個頂級域com域的一個域名,於是就告訴運營商的DNS我不知道這個域名的IP地址,但知道com(頂級)域的IP地址,你去找它,於是運營商的DNS就得到了com域的IP地址,又向com域的IP地址發起請求,com域這臺服務器告訴運營商的DNS我不知道這個域的IP地址,但是我知道權威域名服務器的IP地址,你去找它,於是運營商又向權威域名的DNS地址發起請求,這個時候權威域名服務器一查,果真在我這裏,於是就把找到的結果發送給運營商的DNS服務器,這個時候運營商的DNS服務器你就拿到了這個域名對應的IP地址,並返回給系統內核,內核又把結果返回給瀏覽器。
如果經過以上的4個步驟,還沒有解析成功,那麼會進行如下步驟(以下是針對Windows操作系統):
⑤操作系統就會查找NetBIOS name Cache(NetBIOS名稱緩存,就存在客戶端電腦中的),那這個緩存有什麼東西呢?凡是最近一段時間內和我成功通訊的計算機的計算機名和Ip地址,就都會存在這個緩存裏面。什麼情況下該步能解析成功呢?就是該名稱正好是幾分鐘前和我成功通信過,那麼這一步就可以成功解析。
⑥如果第⑤步也沒有成功,那會查詢WINS 服務器(是NETBIOS名稱和IP地址對應的服務器)
⑦如果第⑥步也沒有查詢成功,那麼客戶端就要進行廣播查找
⑧如果第⑦步也沒有成功,那麼客戶端就讀取LMHOSTS文件(和HOSTS文件同一個目錄下,寫法也一樣)
如果第八步還沒有解析成功,那麼就宣告這次解析失敗,那就無法跟目標計算機進行通信。只要這八步中有一步可以解析成功,那就可以成功和目標計算機進行通信。
原文鏈接:https://blog.csdn.net/u013777975/article/details/80496121
2、與服務器建立連接
客戶端請求到達服務器,首先就是建立TCP連接
三次握手過程:
1)client首先發送一個連接試探,ACK=0表示確認號無效,SYN=1表示這還少一個連接請求或連接接收報文,同時表示這個數據報不能攜帶數據,seq=x表示client自己的初始序號(seq=0就代表這是第0號包),這時候client進入syn_sent狀態,表示客戶端等待服務器的回覆
2)server監聽到連接請求報文後,如果同意建立裏阿尼額,則向client發送確認。Tcp報文首部中的SYN和ACk都置1,ack=x+1表示期望收到對方下一個報文的第一個數據字節號是x+1,同時表明x爲止的所有數據都已正確收到(ack=1其實就是ack=0+1,也就是期望客戶端的第一個包),syn=y表示server自己的初始序號(seq=0就是代表這是服務器這邊發出的第0號包)。這時服務器進入syn_rcvd,表示服務器已經收到client的連接請求,等待client的確認。
3)client收到確認後還需要再次發送確認,同時攜帶要發送給server的數據。ACk置1表示確認號ack=y+1有效(代表期望接收到的服務器的第一個包),client自己的序號seq=x+1(表示這就是我的第一個包,相對於第0個包來說的),一旦收到client的確認之後,這個TCP連接就進入established,就可以發起http請求了。
TCP四次揮手:
-
第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
-
第二次揮手: Server 收到 FIN 後,發送一個 ACK 給 Client ,確認序號爲收到序號 +1 (與 SYN 相同,一個 FIN 佔用一個序號), Server進入 CLOSE_WAIT 狀態。
-
第三次揮手: Server 發送一個 FIN ,用來關閉 Server 到 Client 的數據傳送, Server 進入 LAST_ACK 狀態。
-
第四次揮手: Client 收到 FIN 後, Client 進入 TIME_WAIT 狀態,接着發送一個 ACK 給 Server ,確認序號爲收到序號 +1 , Server 進入CLOSED 狀態,完成四次揮手
【問題1】爲什麼連接的時候是三次握手,關閉的時候卻是四次握手?
答:因爲當Server端收到Client端的SYN連接請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送。故需要四步握手。
【問題2】爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
答:雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最後一個ACK丟失。所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最後的ACK回覆,但該ACK可能丟失。Server如果沒有收到ACK,將不斷重複發送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK之後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。
【問題3】爲什麼不能用兩次握手進行連接?
答:3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被髮送和確認。
現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作爲例子,考慮計算機S和C之間的通信,假定C給S發送一個連接請求分組,S收到了這個分組,併發 送了確認應答分組。按照兩次握手的協定,S認爲連接已經成功地建立了,可以開始發送數據分組。可是,C在S的應答分組在傳輸中被丟失的情況下,將不知道S 是否已準備好,不知道S建立什麼樣的序列號,C甚至懷疑S是否收到自己的連接請求分組。在這種情況下,C認爲連接還未建立成功,將忽略S發來的任何數據分 組,只等待連接確認應答分組。而S在發出的分組超時後,重複發送同樣的分組。這樣就形成了死鎖。
【問題4】如果已經建立了連接,但是客戶端突然出現故障了怎麼辦?
TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。
原文鏈接:https://blog.csdn.net/qq_38950316/article/details/81087809
3、發起HTTP請求
HTTP是一個客戶端和服務器端請求和應答的標準(TCP)。客戶端是終端用戶,服務器端是網站。通過使用web瀏覽器、網絡爬蟲或者其它的工具,客戶端發起一個到服務器上指定端口(默認端口爲80)的HTTP協議進行,否則無法連接。
通俗來講,他就是計算機通過網絡進行通信的規則,是一個基於請求與響應,無狀態的,應用層的協議,常基於TCP/IP協議傳輸數據。目前任何終端之間進行任何一種通信都必須按照HTTP協議進行,否則無法連接。
HTTP請求報文:
一個HTTP請求報文由請求行(request line)、請求頭部(header)、空行和請求數據4個部分組成。
1)請求行
請求行分爲三個部分:請求方法、請求地址和協議版本
請求方法
HTTP/1.1 定義的請求方法有8種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
最常用的兩種GET和POST,如果是RESTful接口的話一般會用到GET、POST、DELETE、PUT。
序號 |
方法 |
描述 |
1 |
GET |
請求指定的頁面信息,並返回實體主體。 |
2 |
HEAD |
類似於 GET 請求,只不過返回的響應中沒有具體的內容,用於獲取報頭 |
3 |
POST |
向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST 請求可能會導致新的資源的建立和/或已有資源的修改。 |
4 |
PUT |
從客戶端向服務器傳送的數據取代指定的文檔的內容。 |
5 |
DELETE |
請求服務器刪除指定的頁面。 |
6 |
CONNECT |
HTTP/1.1 協議中預留給能夠將連接改爲管道方式的代理服務器。 |
7 |
OPTIONS |
允許客戶端查看服務器的性能。 |
8 |
TRACE |
回顯服務器收到的請求,主要用於測試或診斷。 |
9 |
PATCH |
是對 PUT 方法的補充,用來對已知資源進行局部更新 。 |
請求地址
URL:統一資源定位符,是一種自願位置的抽象唯一識別方法。
組成:<協議>://<主機>:<端口>/<路徑>
端口和路徑有時可以省略(HTTP默認端口號是80)
2)請求頭部
請求頭部爲請求報文添加了一些附加信息,由“名/值”對組成,每行一對,名和值之間使用冒號分隔。
請求頭部的最後會有一個空行,表示請求頭部結束,接下來爲請求數據,這一行非常重要,必不可少。
3)請求數據
可選部分,比如GET請求就沒有請求數據。
4、服務器響應HTTP請求,瀏覽器得到HTML代碼
接收到HTTP請求之後,就輪到負載均衡了,它位於網站的最前端,把短時間內較高的訪問量分攤到不同機器上處理。
HTTP響應報文:
HTTP響應報文主要由狀態行、響應頭部、空行以及響應數據組成。
1)狀態行
由3部分組成,分別爲:協議版本,狀態碼,狀態碼描述。
其中協議版本與請求報文一致,狀態碼描述是對狀態碼的簡單描述,所以這裏就只介紹狀態碼。
狀態碼
狀態代碼爲3位數字。
1xx:指示信息–表示請求已接收,繼續處理。
2xx:成功–表示請求已被成功接收、理解、接受。
3xx:重定向–要完成請求必須進行更進一步的操作。
4xx:客戶端錯誤–請求有語法錯誤或請求無法實現。
5xx:服務器端錯誤–服務器未能實現合法的請求。
下面列舉幾個常見的:
HTTP狀態碼列表
狀態碼 |
狀態碼英文名稱 |
中文描述 |
100 |
Continue |
繼續。客戶端應繼續其請求 |
101 |
Switching Protocols |
切換協議。服務器根據客戶端的請求切換協議。只能切換到更高級的協議,例如,切換到HTTP的新版本協議 |
200 |
OK |
請求成功。一般用於GET與POST請求 |
201 |
Created |
已創建。成功請求並創建了新的資源 |
202 |
Accepted |
已接受。已經接受請求,但未處理完成 |
203 |
Non-Authoritative Information |
非授權信息。請求成功。但返回的meta信息不在原始的服務器,而是一個副本 |
204 |
No Content |
無內容。服務器成功處理,但未返回內容。在未更新網頁的情況下,可確保瀏覽器繼續顯示當前文檔 |
205 |
Reset Content |
重置內容。服務器處理成功,用戶終端(例如:瀏覽器)應重置文檔視圖。可通過此返回碼清除瀏覽器的表單域 |
206 |
Partial Content |
部分內容。服務器成功處理了部分GET請求 |
300 |
Multiple Choices |
多種選擇。請求的資源可包括多個位置,相應可返回一個資源特徵與地址的列表用於用戶終端(例如:瀏覽器)選擇 |
301 |
Moved Permanently |
永久移動。請求的資源已被永久的移動到新URI,返回信息會包括新的URI,瀏覽器會自動定向到新URI。今後任何新的請求都應使用新的URI代替 |
302 |
Found |
臨時移動。與301類似。但資源只是臨時被移動。客戶端應繼續使用原有URI |
303 |
See Other |
查看其它地址。與301類似。使用GET和POST請求查看 |
304 |
Not Modified |
未修改。所請求的資源未修改,服務器返回此狀態碼時,不會返回任何資源。客戶端通常會緩存訪問過的資源,通過提供一個頭信息指出客戶端希望只返回在指定日期之後修改的資源 |
305 |
Use Proxy |
使用代理。所請求的資源必須通過代理訪問 |
306 |
Unused |
已經被廢棄的HTTP狀態碼 |
307 |
Temporary Redirect |
臨時重定向。與302類似。使用GET請求重定向 |
400 |
Bad Request |
客戶端請求的語法錯誤,服務器無法理解 |
401 |
Unauthorized |
請求要求用戶的身份認證 |
402 |
Payment Required |
保留,將來使用 |
403 |
Forbidden |
服務器理解請求客戶端的請求,但是拒絕執行此請求 |
404 |
Not Found |
服務器無法根據客戶端的請求找到資源(網頁)。通過此代碼,網站設計人員可設置"您所請求的資源無法找到"的個性頁面 |
405 |
Method Not Allowed |
客戶端請求中的方法被禁止 |
406 |
Not Acceptable |
服務器無法根據客戶端請求的內容特性完成請求 |
407 |
Proxy Authentication Required |
請求要求代理的身份認證,與401類似,但請求者應當使用代理進行授權 |
408 |
Request Time-out |
服務器等待客戶端發送的請求時間過長,超時 |
409 |
Conflict |
服務器完成客戶端的 PUT 請求時可能返回此代碼,服務器處理請求時發生了衝突 |
410 |
Gone |
客戶端請求的資源已經不存在。410不同於404,如果資源以前有現在被永久刪除了可使用410代碼,網站設計人員可通過301代碼指定資源的新位置 |
411 |
Length Required |
服務器無法處理客戶端發送的不帶Content-Length的請求信息 |
412 |
Precondition Failed |
客戶端請求信息的先決條件錯誤 |
413 |
Request Entity Too Large |
由於請求的實體過大,服務器無法處理,因此拒絕請求。爲防止客戶端的連續請求,服務器可能會關閉連接。如果只是服務器暫時無法處理,則會包含一個Retry-After的響應信息 |
414 |
Request-URI Too Large |
請求的URI過長(URI通常爲網址),服務器無法處理 |
415 |
Unsupported Media Type |
服務器無法處理請求附帶的媒體格式 |
416 |
Requested range not satisfiable |
客戶端請求的範圍無效 |
417 |
Expectation Failed |
服務器無法滿足Expect的請求頭信息 |
500 |
Internal Server Error |
服務器內部錯誤,無法完成請求 |
501 |
Not Implemented |
服務器不支持請求的功能,無法完成請求 |
502 |
Bad Gateway |
作爲網關或者代理工作的服務器嘗試執行請求時,從遠程服務器接收到了一個無效的響應 |
503 |
Service Unavailable |
由於超載或系統維護,服務器暫時的無法處理客戶端的請求。延時的長度可包含在服務器的Retry-After頭信息中 |
504 |
Gateway Time-out |
充當網關或代理的服務器,未及時從遠端服務器獲取請求 |
505 |
HTTP Version not supported |
服務器不支持請求的HTTP協議的版本,無法完成處理 |
2)響應頭部
與請求頭部類似,爲響應報文添加了一些附加信息
3)響應數據
用於存放需要返回給客戶端的數據信息。
5、瀏覽器解析html代碼,並請求html代碼中的資源
瀏覽器拿到index.html文件後,就開始解析其中的HTML代碼,遇到js/css/image等靜態資源時,就向服務器端去請求下載(會使用多線程下載,每個瀏覽器的線程數不一樣),這個時候就用上keep-alive特性,建立一個HTTP連接,可以請求多個資源,下載資源的順序就是按照代碼裏的順序,但由於每個資源大小不一樣,而瀏覽器又多線程請求資,所以顯示的順序不一定是代碼裏面的順序。
瀏覽器在請求靜態資源時(在未過期的情況下),向服務器端發起一個HTTP請求(詢問自從上一次修改時間到現在有沒有對資源進行修改),如果服務器端返回304狀態碼(告訴瀏覽器端沒有修改),那麼瀏覽器會直接讀取本地的該資源的緩存文件。
6、瀏覽器對頁面進行渲染呈現給用戶
最後,瀏覽器利用自己內部的工作機制,把請求到的靜態資源和html代碼進行渲染,渲染之後呈現給用戶。