網絡之一次http請求的完整過程


關於網絡的知識平時可能真正用的比較少,但是有一些點還是需要總結的:

完成一次http請求要大致可以分為7個步驟:

一、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請求報文

一個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。

請求地址

URL:統一資源定位符,是一種自願位置的抽象唯一識別方法。

組成:<協議>://<主機>:<端口>/<路徑>

端口和路徑有時可以省略(HTTP默認端口號是80)

如下例:

有時會帶參數,GET請求

協議版本

協議版本的格式為:HTTP/主版本號.次版本號,常用的有HTTP/1.0和HTTP/1.1

2.請求頭部

請求頭部為請求報文添加了一些附加信息,由“名/值”對組成,每行一對,名和值之間使用冒號分隔。

常見請求頭如下:

請求頭部的最后會有一個空行,表示請求頭部結束,接下來為請求數據,這一行非常重要,必不可少。

3.請求數據

可選部分,比如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響應報文主要由狀態行、響應頭部、空行以及響應數據組成。

1.狀態行

由3部分組成,分別為:協議版本,狀態碼,狀態碼描述。

其中協議版本與請求報文一致,狀態碼描述是對狀態碼的簡單描述,所以這里就只介紹狀態碼。

狀態碼

狀態代碼為3位數字。
1xx:指示信息--表示請求已接收,繼續處理。
2xx:成功--表示請求已被成功接收、理解、接受。
3xx:重定向--要完成請求必須進行更進一步的操作。
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現。
5xx:服務器端錯誤--服務器未能實現合法的請求。

下面列舉幾個常見的:


2.響應頭部

與請求頭部類似,為響應報文添加了一些附加信息

常見響應頭部如下:


3.響應數據

用於存放需要返回給客戶端的數據信息。

下面是一個響應報文的實例:

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連接。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM