做者:Ruheng
http://www.jianshu.com/p/c1d6...本文以HTTP請求和響應的過程來說解涉及到的相關知識點。php
第一html
HTTP請求和相應步驟java
圖片來自:理解Http請求與響應http://android.jobbole.com/85...android
以上完整表示了HTTP請求和響應的7個步驟,下面從TCP/IP協議模型的角度來理解HTTP請求和響應如何傳遞的。面試
第二後端
TCP/IP協議瀏覽器
TCP/IP協議模型(Transmission Control Protocol/Internet Protocol),包含了一系列構成互聯網基礎的網絡協議,是Internet的核心協議,經過20多年的發展已日漸成熟,並被普遍應用於局域網和廣域網中,目前已成爲事實上的國際標準。TCP/IP協議簇是一組不一樣層次上的多個協議的組合,一般被認爲是一個四層協議系統,與OSI的七層模型相對應。安全
HTTP協議就是基於TCP/IP協議模型來傳輸信息的。服務器
(1). 鏈路層網絡
也稱做數據鏈路層或網絡接口層(在第一個圖中爲網絡接口層和硬件層),一般包括操做系統中的設備驅動程序和計算機中對應的網絡接口卡。它們一塊兒處理與電纜(或其餘任何傳輸媒介)的物理接口細節。ARP(地址解析協議)和RARP(逆地址解析協議)是某些網絡接口(如以太網和令牌環網)使用的特殊協議,用來轉換IP層和網絡接口層使用的地址。
(2). 網絡層
也稱做互聯網層(在第一個圖中爲網際層),處理分組在網絡中的活動,例如分組的選路。在TCP/IP協議族中,網絡層協議包括IP協議(網際協議),ICMP協議(Internet互聯網控制報文協議),以及IGMP協議(Internet組管理協議)。
IP是一種網絡層協議,提供的是一種不可靠的服務,它只是儘量快地把分組從源結點送到目的結點,可是並不提供任何可靠性保證。同時被TCP和UDP使用。TCP和UDP的每組數據都經過端系統和每一箇中間路由器中的IP層在互聯網中進行傳輸。
ICMP是IP協議的附屬協議。IP層用它來與其餘主機或路由器交換錯誤報文和其餘重要信息。
IGMP是Internet組管理協議。它用來把一個UDP數據報多播到多個主機。
(3). 傳輸層
主要爲兩臺主機上的應用程序提供端到端的通訊。在TCP/IP協議族中,有兩個互不相同的傳輸協議:TCP(傳輸控制協議)和UDP(用戶數據報協議)。
TCP爲兩臺主機提供高可靠性的數據通訊。它所作的工做包括把應用程序交給它的數據分紅合適的小塊交給下面的網絡層,確認接收到的分組,設置發送最後確認分組的超時時鐘等。因爲運輸層提供了高可靠性的端到端的通訊,所以應用層能夠忽略全部這些細節。爲了提供可靠的服務,TCP採用了超時重傳、發送和接收端到端的確認分組等機制。
UDP則爲應用層提供一種很是簡單的服務。它只是把稱做數據報的分組從一臺主機發送到另外一臺主機,但並不保證該數據報能到達另外一端。一個數據報是指從發送方傳輸到接收方的一個信息單元(例如,發送方指定的必定字節數的信息)。UDP協議任何須需的可靠性必須由應用層來提供。
(4). 應用層
應用層決定了向用戶提供應用服務時通訊的活動。TCP/IP 協議族內預存了各種通用的應用服務。包括 HTTP,FTP(File Transfer Protocol,文件傳輸協議),DNS(Domain Name System,域名系統)服務。
當應用程序用TCP傳送數據時,數據被送入協議棧中,而後逐個經過每一層直到被看成一串比特流送入網絡。其中每一層對收到的數據都要增長一些首部信息(有時還要增長尾部信息),該過程如圖所示。
當目的主機收到一個以太網數據幀時,數據就開始從協議棧中由底向上升,同時去掉各層協議加上的報文首部。每層協議盒都要去檢查報文首部中的協議標識,以肯定接收數據的上層協議。這個過程稱做分用(Demultiplexing)。協議是經過目的端口號、源I P地址和源端口號進行解包的。
經過以上步驟咱們從TCP/IP模型的角度來理解了一次HTTP請求與響應的過程。
下面這張圖更清楚明白:
下面具體來看如何進行一步步操做的。
第三
TCP三次握手
TCP是面向鏈接的,不管哪一方向另外一方發送數據以前,都必須先在雙方之間創建一條鏈接。在TCP/IP協議中,TCP協議提供可靠的鏈接服務,鏈接是經過三次握手進行初始化的。三次握手的目的是同步鏈接雙方的序列號和確認號並交換 TCP窗口大小信息。
第一次握手:創建鏈接。客戶端發送鏈接請求報文段,將SYN位置爲1,Sequence Number爲x;而後,客戶端進入SYN_SEND狀態,等待服務器的確認;
第二次握手:服務器收到SYN報文段。服務器收到客戶端的SYN報文段,須要對這個SYN報文段進行確認,設置Acknowledgment Number爲x+1(Sequence Number+1);同時,本身本身還要發送SYN請求信息,將SYN位置爲1,Sequence Number爲y;服務器端將上述全部信息放到一個報文段(即SYN+ACK報文段)中,一併發送給客戶端,此時服務器進入SYN_RECV狀態;
第三次握手:客戶端收到服務器的SYN+ACK報文段。而後將Acknowledgment Number設置爲y+1,向服務器發送ACK報文段,這個報文段發送完畢之後,客戶端和服務器端都進入ESTABLISHED狀態,完成TCP三次握手。
爲了防止已失效的鏈接請求報文段忽然又傳送到了服務端,於是產生錯誤。
具體例子:「已失效的鏈接請求報文段」的產生在這樣一種狀況下:client發出的第一個鏈接請求報文段並無丟失,而是在某個網絡結點長時間的滯留了,以至延誤到鏈接釋放之後的某個時間纔到達server。原本這是一個早已失效的報文段。但server收到此失效的鏈接請求報文段後,就誤認爲是client再次發出的一個新的鏈接請求。因而就向client發出確認報文段,贊成創建鏈接。假設不採用「三次握手」,那麼只要server發出確認,新的鏈接就創建了。因爲如今client並無發出創建鏈接的請求,所以不會理睬server的確認,也不會向server發送數據。但server卻覺得新的運輸鏈接已經創建,並一直等待client發來數據。這樣,server的不少資源就白白浪費掉了。採用「三次握手」的辦法能夠防止上述現象發生。例如剛纔那種狀況,client不會向server的確認發出確認。server因爲收不到確認,就知道client並無要求創建鏈接。」
第四
HTTP協議
通俗來說,他就是計算機經過網絡進行通訊的規則,是一個基於請求與響應,無狀態的,應用層的協議,常基於TCP/IP協議傳輸數據。目前任何終端(手機,筆記本電腦。。)之間進行任何一種通訊都必須按照Http協議進行,不然沒法鏈接。
四個基於:
請求與響應:客戶端發送請求,服務器端響應數據
無狀態的:協議對於事務處理沒有記憶能力,客戶端第一次與服務器創建鏈接發送請求時須要進行一系列的安全認證匹配等,所以增長頁面等待時間,當客戶端向服務器端發送請求,服務器端響應完畢後,二者斷開鏈接,也不保存鏈接狀態,一刀兩斷!恩斷義絕!今後路人!下一次客戶端向一樣的服務器發送請求時,因爲他們以前已經遺忘了彼此,因此須要從新創建鏈接。
應用層:Http是屬於應用層的協議,配合TCP/IP使用。
TCP/IP:Http使用TCP做爲它的支撐運輸協議。HTTP客戶機發起一個與服務器的TCP鏈接,一旦鏈接創建,瀏覽器(客戶機)和服務器進程就能夠經過套接字接口訪問TCP。
針對無狀態的一些解決策略:
有時須要對用戶以前的HTTP通訊狀態進行保存,好比執行一次登錄操做,在30分鐘內全部的請求都不須要再次登錄。因而引入了Cookie技術。
HTTP/1.1想出了持久鏈接(HTTP keep-alive)方法。其特色是,只要任意一端沒有明確提出斷開鏈接,則保持TCP鏈接狀態,在請求首部字段中的Connection: keep-alive即爲代表使用了持久鏈接。
等等還有不少。。。。。。
下面開始講解重頭戲:HTTP請求報文,響應報文,對應於上述步驟的2,3,4,5,6。
HTTP報文是面向文本的,報文中的每個字段都是一些ASCII碼串,各個字段的長度是不肯定的。HTTP有兩類報文:請求報文和響應報文。
第五
HTTP請求報文
一個HTTP請求報文由請求行(request line)、請求頭部(header)、空行和請求數據4個部分組成,下圖給出了請求報文的通常格式。
請求行分爲三個部分:請求方法、請求地址和協議版本
請求方法
HTTP/1.1 定義的請求方法有8種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
最常的兩種GET和POST,若是是RESTful接口的話通常會用到GET、POST、DELETE、PUT。
請求地址
URL:統一資源定位符,是一種自願位置的抽象惟一識別方法。
組成:<協議>://<主機>:<端口>/<路徑>
端口和路徑有時能夠省略(HTTP默認端口號是80)
以下例:
有時會帶參數,GET請求
協議版本
協議版本的格式爲:HTTP/主版本號.次版本號,經常使用的有HTTP/1.0和HTTP/1.1
請求頭部爲請求報文添加了一些附加信息,由「名/值」對組成,每行一對,名和值之間使用冒號分隔。
常見請求頭以下:
請求頭部的最後會有一個空行,表示請求頭部結束,接下來爲請求數據,這一行很是重要,必不可少。
可選部分,好比GET請求就沒有請求數據。
下面是一個POST方法的請求報文:
POST /index.php HTTP/1.1 請求行
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2 請求頭
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,_/_;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost/
Content-Length:25
Content-Type:application/x-www-form-urlencoded
空行
username=aa&password=1234 請求數據
第六
HTTP響應報文
HTTP響應報文主要由狀態行、響應頭部、空行以及響應數據組成。
由3部分組成,分別爲:協議版本,狀態碼,狀態碼描述。
其中協議版本與請求報文一致,狀態碼描述是對狀態碼的簡單描述,因此這裏就只介紹狀態碼。
狀態碼
狀態代碼爲3位數字。
1xx:指示信息--表示請求已接收,繼續處理。
2xx:成功--表示請求已被成功接收、理解、接受。
3xx:重定向--要完成請求必須進行更進一步的操做。
4xx:客戶端錯誤--請求有語法錯誤或請求沒法實現。
5xx:服務器端錯誤--服務器未能實現合法的請求。
下面列舉幾個常見的:兩張趣圖助你理解 HTTP 狀態碼!
與請求頭部相似,爲響應報文添加了一些附加信息
常見響應頭部以下:
用於存放須要返回給客戶端的數據信息。
下面是一個響應報文的實例:
HTTP/1.1 200 OK 狀態行
Date: Sun, 17 Mar 2013 08:12:54 GMT 響應頭部
Server: Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By: PHP/5.2.5
Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 4393
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
空行<html> 響應數據
<head>
<title>HTTP響應示例<title>
</head>
<body>
Hello HTTP!
</body>
</html>
關於請求頭部和響應頭部的知識點不少,這裏只是簡單介紹。
經過以上步驟,數據已經傳遞完畢,HTTP/1.1會維持持久鏈接,但持續一段時間總會有關閉鏈接的時候,這時候據須要斷開TCP鏈接。
第七
TCP四次揮手
當客戶端和服務器經過三次握手創建了TCP鏈接之後,當數據傳送完畢,確定是要斷開TCP鏈接的啊。那對於TCP的斷開鏈接,這裏就有了神祕的「四次分手」。
第一次分手:主機1(可使客戶端,也能夠是服務器端),設置Sequence Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;
第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number爲Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我「贊成」你的關閉請求;
第三次分手:主機2向主機1發送FIN報文段,請求關閉鏈接,同時主機2進入LAST_ACK狀態;
第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,而後主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段之後,就關閉鏈接;此時,主機1等待2MSL後依然沒有收到回覆,則證實Server端已正常關閉,那好,主機1也能夠關閉鏈接了。
TCP協議是一種面向鏈接的、可靠的、基於字節流的運輸層通訊協議。TCP是全雙工模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經所有發送完畢了;可是,這個時候主機1仍是能夠接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,可是主機2仍是能夠發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,以後彼此就會愉快的中斷此次TCP鏈接。
經過以上步驟便完成了HTTP的請求和響應,進行了數據傳遞,這其中涉及到須要知識點,都進行了逐一瞭解。
推薦去個人博客閱讀更多:
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
以爲不錯,別忘了點贊+轉發哦!