本文以HTTP請求和響應(yīng)的過程來講解涉及到的相關(guān)知識點。
第一
HTTP請求和相應(yīng)步驟
圖片來自:理解Http請求與響應(yīng)http://android.jobbole.com/85218/
以上完整表示了HTTP請求和響應(yīng)的7個步驟,下面從TCP/IP協(xié)議模型的角度來理解HTTP請求和響應(yīng)如何傳遞的肋层。
第二
TCP/IP協(xié)議
TCP/IP協(xié)議模型(Transmission Control Protocol/Internet Protocol)奴艾,包含了一系列構(gòu)成互聯(lián)網(wǎng)基礎(chǔ)的網(wǎng)絡(luò)協(xié)議净当,是Internet的核心協(xié)議,通過20多年的發(fā)展已日漸成熟蕴潦,并被廣泛應(yīng)用于局域網(wǎng)和廣域網(wǎng)中像啼,目前已成為事實上的國際標(biāo)準(zhǔn)。TCP/IP協(xié)議簇是一組不同層次上的多個協(xié)議的組合潭苞,通常被認(rèn)為是一個四層協(xié)議系統(tǒng)忽冻,與OSI的七層模型相對應(yīng)。
HTTP協(xié)議就是基于TCP/IP協(xié)議模型來傳輸信息的此疹。
(1). 鏈路層
也稱作數(shù)據(jù)鏈路層或網(wǎng)絡(luò)接口層(在第一個圖中為網(wǎng)絡(luò)接口層和硬件層)僧诚,通常包括操作系統(tǒng)中的設(shè)備驅(qū)動程序和計算機中對應(yīng)的網(wǎng)絡(luò)接口卡。它們一起處理與電纜(或其他任何傳輸媒介)的物理接口細(xì)節(jié)蝗碎。ARP(地址解析協(xié)議)和RARP(逆地址解析協(xié)議)是某些網(wǎng)絡(luò)接口(如以太網(wǎng)和令牌環(huán)網(wǎng))使用的特殊協(xié)議湖笨,用來轉(zhuǎn)換IP層和網(wǎng)絡(luò)接口層使用的地址。
(2). 網(wǎng)絡(luò)層
也稱作互聯(lián)網(wǎng)層(在第一個圖中為網(wǎng)際層)蹦骑,處理分組在網(wǎng)絡(luò)中的活動慈省,例如分組的選路。在TCP/IP協(xié)議族中眠菇,網(wǎng)絡(luò)層協(xié)議包括IP協(xié)議(網(wǎng)際協(xié)議)边败,ICMP協(xié)議(Internet互聯(lián)網(wǎng)控制報文協(xié)議),以及IGMP協(xié)議(Internet組管理協(xié)議)琼锋。
IP是一種網(wǎng)絡(luò)層協(xié)議放闺,提供的是一種不可靠的服務(wù),它只是盡可能快地把分組從源結(jié)點送到目的結(jié)點缕坎,但是并不提供任何可靠性保證怖侦。同時被TCP和UDP使用。TCP和UDP的每組數(shù)據(jù)都通過端系統(tǒng)和每個中間路由器中的IP層在互聯(lián)網(wǎng)中進(jìn)行傳輸谜叹。
ICMP是IP協(xié)議的附屬協(xié)議匾寝。IP層用它來與其他主機或路由器交換錯誤報文和其他重要信息。
IGMP是Internet組管理協(xié)議荷腊。它用來把一個UDP數(shù)據(jù)報多播到多個主機艳悔。
(3). 傳輸層
主要為兩臺主機上的應(yīng)用程序提供端到端的通信。在TCP/IP協(xié)議族中女仰,有兩個互不相同的傳輸協(xié)議:TCP(傳輸控制協(xié)議)和UDP(用戶數(shù)據(jù)報協(xié)議)猜年。
TCP為兩臺主機提供高可靠性的數(shù)據(jù)通信抡锈。它所做的工作包括把應(yīng)用程序交給它的數(shù)據(jù)分成合適的小塊交給下面的網(wǎng)絡(luò)層,確認(rèn)接收到的分組乔外,設(shè)置發(fā)送最后確認(rèn)分組的超時時鐘等床三。由于運輸層提供了高可靠性的端到端的通信,因此應(yīng)用層可以忽略所有這些細(xì)節(jié)杨幼。為了提供可靠的服務(wù)撇簿,TCP采用了超時重傳、發(fā)送和接收端到端的確認(rèn)分組等機制差购。
UDP則為應(yīng)用層提供一種非常簡單的服務(wù)四瘫。它只是把稱作數(shù)據(jù)報的分組從一臺主機發(fā)送到另一臺主機,但并不保證該數(shù)據(jù)報能到達(dá)另一端欲逃。一個數(shù)據(jù)報是指從發(fā)送方傳輸?shù)浇邮辗降囊粋€信息單元(例如找蜜,發(fā)送方指定的一定字節(jié)數(shù)的信息)。UDP協(xié)議任何必需的可靠性必須由應(yīng)用層來提供稳析。
(4). 應(yīng)用層
應(yīng)用層決定了向用戶提供應(yīng)用服務(wù)時通信的活動锹杈。TCP/IP 協(xié)議族內(nèi)預(yù)存了各類通用的應(yīng)用服務(wù)。包括 HTTP迈着,F(xiàn)TP(File Transfer Protocol,文件傳輸協(xié)議)邪码,DNS(Domain Name System裕菠,域名系統(tǒng))服務(wù)。
當(dāng)應(yīng)用程序用TCP傳送數(shù)據(jù)時闭专,數(shù)據(jù)被送入?yún)f(xié)議棧中奴潘,然后逐個通過每一層直到被當(dāng)作一串比特流送入網(wǎng)絡(luò)。其中每一層對收到的數(shù)據(jù)都要增加一些首部信息(有時還要增加尾部信息)影钉,該過程如圖所示画髓。
當(dāng)目的主機收到一個以太網(wǎng)數(shù)據(jù)幀時,數(shù)據(jù)就開始從協(xié)議棧中由底向上升平委,同時去掉各層協(xié)議加上的報文首部奈虾。每層協(xié)議盒都要去檢查報文首部中的協(xié)議標(biāo)識,以確定接收數(shù)據(jù)的上層協(xié)議廉赔。這個過程稱作分用(Demultiplexing)肉微。協(xié)議是通過目的端口號、源I P地址和源端口號進(jìn)行解包的蜡塌。
通過以上步驟我們從TCP/IP模型的角度來理解了一次HTTP請求與響應(yīng)的過程碉纳。
下面這張圖更清楚明白:
下面具體來看如何進(jìn)行一步步操作的。
第三
TCP三次握手
TCP是面向連接的馏艾,無論哪一方向另一方發(fā)送數(shù)據(jù)之前劳曹,都必須先在雙方之間建立一條連接奴愉。在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù)铁孵,連接是通過三次握手進(jìn)行初始化的锭硼。三次握手的目的是同步連接雙方的序列號和確認(rèn)號并交換 TCP窗口大小信息。
第一次握手:建立連接库菲≌送客戶端發(fā)送連接請求報文段,將SYN位置為1熙宇,Sequence Number為x鳖擒;然后,客戶端進(jìn)入SYN_SEND狀態(tài)烫止,等待服務(wù)器的確認(rèn)蒋荚;
第二次握手:服務(wù)器收到SYN報文段。服務(wù)器收到客戶端的SYN報文段馆蠕,需要對這個SYN報文段進(jìn)行確認(rèn)期升,設(shè)置Acknowledgment Number為x+1(Sequence Number+1);同時互躬,自己自己還要發(fā)送SYN請求信息播赁,將SYN位置為1,Sequence Number為y吼渡;服務(wù)器端將上述所有信息放到一個報文段(即SYN+ACK報文段)中容为,一并發(fā)送給客戶端,此時服務(wù)器進(jìn)入SYN_RECV狀態(tài)寺酪;
第三次握手:客戶端收到服務(wù)器的SYN+ACK報文段坎背。然后將Acknowledgment Number設(shè)置為y+1,向服務(wù)器發(fā)送ACK報文段寄雀,這個報文段發(fā)送完畢以后得滤,客戶端和服務(wù)器端都進(jìn)入ESTABLISHED狀態(tài),完成TCP三次握手盒犹。
為什么要三次握手
為了防止已失效的連接請求報文段突然又傳送到了服務(wù)端懂更,因而產(chǎn)生錯誤。
具體例子:“已失效的連接請求報文段”的產(chǎn)生在這樣一種情況下:client發(fā)出的第一個連接請求報文段并沒有丟失急膀,而是在某個網(wǎng)絡(luò)結(jié)點長時間的滯留了膜蛔,以致延誤到連接釋放以后的某個時間才到達(dá)server。本來這是一個早已失效的報文段脖阵。
但server收到此失效的連接請求報文段后皂股,就誤認(rèn)為是client再次發(fā)出的一個新的連接請求。于是就向client發(fā)出確認(rèn)報文段命黔,同意建立連接呜呐。假設(shè)不采用“三次握手”就斤,那么只要server發(fā)出確認(rèn),新的連接就建立了蘑辑。
由于現(xiàn)在client并沒有發(fā)出建立連接的請求洋机,因此不會理睬server的確認(rèn),也不會向server發(fā)送數(shù)據(jù)洋魂。但server卻以為新的運輸連接已經(jīng)建立绷旗,并一直等待client發(fā)來數(shù)據(jù)。這樣副砍,server的很多資源就白白浪費掉了衔肢。
采用“三次握手”的辦法可以防止上述現(xiàn)象發(fā)生。例如剛才那種情況豁翎,client不會向server的確認(rèn)發(fā)出確認(rèn)角骤。server由于收不到確認(rèn),就知道client并沒有要求建立連接心剥“钭穑”
第四
HTTP協(xié)議
Http是什么?
通俗來講优烧,他就是計算機通過網(wǎng)絡(luò)進(jìn)行通信的規(guī)則蝉揍,是一個基于請求與響應(yīng),無狀態(tài)的畦娄,應(yīng)用層的協(xié)議疑苫,常基于TCP/IP協(xié)議傳輸數(shù)據(jù)纷责。目前任何終端(手機,筆記本電腦撼短。再膳。)之間進(jìn)行任何一種通信都必須按照Http協(xié)議進(jìn)行,否則無法連接曲横。
四個基于:
請求與響應(yīng):客戶端發(fā)送請求喂柒,服務(wù)器端響應(yīng)數(shù)據(jù)
無狀態(tài)的:協(xié)議對于事務(wù)處理沒有記憶能力,客戶端第一次與服務(wù)器建立連接發(fā)送請求時需要進(jìn)行一系列的安全認(rèn)證匹配等禾嫉,因此增加頁面等待時間灾杰,當(dāng)客戶端向服務(wù)器端發(fā)送請求,服務(wù)器端響應(yīng)完畢后熙参,兩者斷開連接艳吠,也不保存連接狀態(tài),一刀兩斷孽椰!恩斷義絕昭娩!從此路人凛篙!下一次客戶端向同樣的服務(wù)器發(fā)送請求時,由于他們之前已經(jīng)遺忘了彼此栏渺,所以需要重新建立連接呛梆。
應(yīng)用層:Http是屬于應(yīng)用層的協(xié)議,配合TCP/IP使用磕诊。
TCP/IP:Http使用TCP作為它的支撐運輸協(xié)議填物。HTTP客戶機發(fā)起一個與服務(wù)器的TCP連接,一旦連接建立霎终,瀏覽器(客戶機)和服務(wù)器進(jìn)程就可以通過套接字接口訪問TCP滞磺。
針對無狀態(tài)的一些解決策略:
有時需要對用戶之前的HTTP通信狀態(tài)進(jìn)行保存,比如執(zhí)行一次登陸操作神僵,在30分鐘內(nèi)所有的請求都不需要再次登陸雁刷。于是引入了Cookie技術(shù)。
HTTP/1.1想出了持久連接(HTTP keep-alive)方法保礼。其特點是沛励,只要任意一端沒有明確提出斷開連接,則保持TCP連接狀態(tài)炮障,在請求首部字段中的Connection: keep-alive即為表明使用了持久連接目派。
等等還有很多。胁赢。企蹭。。智末。谅摄。
下面開始講解重頭戲:HTTP請求報文,響應(yīng)報文系馆,對應(yīng)于上述步驟的2送漠,3,4由蘑,5闽寡,6。
HTTP報文是面向文本的尼酿,報文中的每一個字段都是一些ASCII碼串爷狈,各個字段的長度是不確定的。HTTP有兩類報文:請求報文和響應(yīng)報文裳擎。
第五
HTTP請求報文
一個HTTP請求報文由請求行(request line)涎永、請求頭部(header)、空行和請求數(shù)據(jù)4個部分組成,下圖給出了請求報文的一般格式土辩。
1.請求行
請求行分為三個部分:請求方法筒严、請求地址和協(xié)議版本
請求方法
HTTP/1.1 定義的請求方法有8種:GET骨宠、POST、PUT、DELETE忆绰、PATCH孵班、HEAD困肩、OPTIONS带族、TRACE。
最常的兩種GET和POST结洼,如果是RESTful接口的話一般會用到GET黎做、POST、DELETE松忍、PUT蒸殿。
請求地址
URL:統(tǒng)一資源定位符,是一種自愿位置的抽象唯一識別方法鸣峭。
組成:<協(xié)議>://<主機>:<端口>/<路徑>
端口和路徑有時可以省略(HTTP默認(rèn)端口號是80)
如下例:
有時會帶參數(shù)宏所,GET請求
協(xié)議版本
協(xié)議版本的格式為:HTTP/主版本號.次版本號,常用的有HTTP/1.0和HTTP/1.1
2.請求頭部
請求頭部為請求報文添加了一些附加信息摊溶,由“名/值”對組成爬骤,每行一對,名和值之間使用冒號分隔莫换。
常見請求頭如下:
請求頭部的最后會有一個空行霞玄,表示請求頭部結(jié)束,接下來為請求數(shù)據(jù)拉岁,這一行非常重要坷剧,必不可少。
3.請求數(shù)據(jù)
可選部分喊暖,比如GET請求就沒有請求數(shù)據(jù)惫企。
下面是一個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 請求數(shù)據(jù)
第六
HTTP響應(yīng)報文
HTTP響應(yīng)報文主要由狀態(tài)行、響應(yīng)頭部哄啄、空行以及響應(yīng)數(shù)據(jù)組成。
1.狀態(tài)行
由3部分組成风范,分別為:協(xié)議版本咨跌,狀態(tài)碼,狀態(tài)碼描述硼婿。
其中協(xié)議版本與請求報文一致锌半,狀態(tài)碼描述是對狀態(tài)碼的簡單描述,所以這里就只介紹狀態(tài)碼寇漫。
狀態(tài)碼
狀態(tài)代碼為3位數(shù)字刊殉。
1xx:指示信息--表示請求已接收殉摔,繼續(xù)處理。
2xx:成功--表示請求已被成功接收记焊、理解逸月、接受。
3xx:重定向--要完成請求必須進(jìn)行更進(jìn)一步的操作遍膜。
4xx:客戶端錯誤--請求有語法錯誤或請求無法實現(xiàn)碗硬。
5xx:服務(wù)器端錯誤--服務(wù)器未能實現(xiàn)合法的請求。
下面列舉幾個常見的:兩張趣圖助你理解 HTTP 狀態(tài)碼瓢颅!
2.響應(yīng)頭部
與請求頭部類似恩尾,為響應(yīng)報文添加了一些附加信息
常見響應(yīng)頭部如下:
3.響應(yīng)數(shù)據(jù)
用于存放需要返回給客戶端的數(shù)據(jù)信息。
下面是一個響應(yīng)報文的實例:
HTTP/1.1?200?OK 狀態(tài)行
Date:?Sun,?17?Mar?2013?08:12:54?GMT 響應(yīng)頭部
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
空行
響應(yīng)數(shù)據(jù)
HTTP響應(yīng)示例<title>
Hello?HTTP!
關(guān)于請求頭部和響應(yīng)頭部的知識點很多挽懦,這里只是簡單介紹翰意。
通過以上步驟,數(shù)據(jù)已經(jīng)傳遞完畢信柿,HTTP/1.1會維持持久連接冀偶,但持續(xù)一段時間總會有關(guān)閉連接的時候,這時候據(jù)需要斷開TCP連接角塑。
第七
TCP四次揮手
當(dāng)客戶端和服務(wù)器通過三次握手建立了TCP連接以后蔫磨,當(dāng)數(shù)據(jù)傳送完畢,肯定是要斷開TCP連接的啊圃伶。那對于TCP的斷開連接堤如,這里就有了神秘的“四次分手”。
第一次分手:主機1(可以使客戶端窒朋,也可以是服務(wù)器端)搀罢,設(shè)置Sequence Number,向主機2發(fā)送一個FIN報文段侥猩;此時榔至,主機1進(jìn)入FIN_WAIT_1狀態(tài);這表示主機1沒有數(shù)據(jù)要發(fā)送給主機2了欺劳;
第二次分手:主機2收到了主機1發(fā)送的FIN報文段唧取,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1划提;主機1進(jìn)入FIN_WAIT_2狀態(tài)枫弟;主機2告訴主機1,我“同意”你的關(guān)閉請求鹏往;
第三次分手:主機2向主機1發(fā)送FIN報文段淡诗,請求關(guān)閉連接,同時主機2進(jìn)入LAST_ACK狀態(tài);
第四次分手:主機1收到主機2發(fā)送的FIN報文段韩容,向主機2發(fā)送ACK報文段款违,然后主機1進(jìn)入TIME_WAIT狀態(tài);主機2收到主機1的ACK報文段以后群凶,就關(guān)閉連接插爹;此時,主機1等待2MSL后依然沒有收到回復(fù)座掘,則證明Server端已正常關(guān)閉递惋,那好,主機1也可以關(guān)閉連接了溢陪。
為什么要四次分手
TCP協(xié)議是一種面向連接的萍虽、可靠的、基于字節(jié)流的運輸層通信協(xié)議形真。
TCP是全雙工模式杉编,這就意味著,當(dāng)主機1發(fā)出FIN報文段時咆霜,只是表示主機1已經(jīng)沒有數(shù)據(jù)要發(fā)送了邓馒,主機1告訴主機2,它的數(shù)據(jù)已經(jīng)全部發(fā)送完畢了蛾坯;但是光酣,這個時候主機1還是可以接受來自主機2的數(shù)據(jù);
當(dāng)主機2返回ACK報文段時脉课,表示它已經(jīng)知道主機1沒有數(shù)據(jù)發(fā)送了救军,但是主機2還是可以發(fā)送數(shù)據(jù)到主機1的;當(dāng)主機2也發(fā)送了FIN報文段時倘零,這個時候就表示主機2也沒有數(shù)據(jù)要發(fā)送了唱遭,就會告訴主機1,我也沒有數(shù)據(jù)要發(fā)送了呈驶,之后彼此就會愉快的中斷這次TCP連接拷泽。
通過以上步驟便完成了HTTP的請求和響應(yīng),進(jìn)行了數(shù)據(jù)傳遞袖瞻,這其中涉及到需要知識點司致,都進(jìn)行了逐一了解。
如果你對編程感興趣或者想往編程方向發(fā)展聋迎,可以關(guān)注微信公眾號【筑夢編程】脂矫,大家一起交流討論!小編也會每天定時更新既有趣又有用的編程知識砌庄!