常見的 HTTP 請(qǐng)求類型
一、TCP報(bào)文格式

其中比較重要的字段有:
1??序號(hào)(sequence number):Seq ,占 32 位,用來標(biāo)識(shí)從 TCP 源端向目的端發(fā)送的字節(jié)流,發(fā)起方發(fā)送數(shù)據(jù)時(shí)對(duì)此進(jìn)行標(biāo)記。
2??確認(rèn)號(hào)(acknowledgement number):Ack,占 32 位,只有 ACK 標(biāo)志位為 1 時(shí),確認(rèn)序號(hào)字段才有效,Ack=Seq+1。
3??標(biāo)志位(Flags):共 6 個(gè),即 URG、ACK、PSH、RST、SYN、FIN 等。具體含義如下:
- URG:緊急指針(urgent pointer)有效。
- ACK:確認(rèn)序號(hào)有效。
- PSH:接收方應(yīng)該盡快將這個(gè)報(bào)文交給應(yīng)用層。
- RST:重置連接。
- SYN:發(fā)起一個(gè)新連接。
- FIN:釋放一個(gè)連接。
注意:切記不要將確認(rèn)號(hào) Ack 與標(biāo)志位中的 ACK 搞混了。確認(rèn)方Ack=發(fā)起方Seq+1,兩端配對(duì)。
二、TCP三次握手(Three-Way Handshake)

TCP,名為傳輸控制協(xié)議,是一種可靠的傳輸層協(xié)議,IP 協(xié)議號(hào)為 6。原則上任何數(shù)據(jù)傳輸都無法確保絕對(duì)可靠,三次握手只是確??煽康幕拘枰?。在 TCP/IP 中,TCP 提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接。這個(gè)連接必須是一方主動(dòng)打開,另一方被動(dòng)打開的。握手之前主動(dòng)打開連接的客戶端結(jié)束 CLOSED 階段,被動(dòng)打開的服務(wù)器也結(jié)束 CLOSED 階段,并進(jìn)入 LISTEN 階段。隨后開始“三次握手”:
1??第一次握手:客戶端向服務(wù)器發(fā)送一段 TCP 報(bào)文,包括:
- 標(biāo)志位為 SYN,表示“請(qǐng)求建立新連接”。
- 序號(hào)為 Seq=x (x一般為1)。
- 隨后客戶端進(jìn)入 SYN_SENT 階段,等待服務(wù)器確認(rèn)。
2??第二次握手:服務(wù)器接收到來自客戶端的 TCP 報(bào)文之后,結(jié)束 LISTEN 階段。并返回一段 TCP 報(bào)文,包括:
- 標(biāo)志位為 SYN 和 ACK,表示“確認(rèn)客戶端的報(bào)文 Seq 有效,服務(wù)器能正常接收客戶端發(fā)送的數(shù)據(jù),并同意創(chuàng)建新連接”。
- 序號(hào)為 Seq=y。
- 確認(rèn)號(hào)為 Ack=x+1
表示收到客戶端的 Seq 并將其值 +1 作為自己確認(rèn)號(hào) Ack 的值。隨后服務(wù)器進(jìn)入 SYN-RCVD 階段。
3??第三次握手:客戶端接收到來自服務(wù)器的確認(rèn)收到數(shù)據(jù)的 TCP 報(bào)文之后,明確了從客戶端到服務(wù)器的數(shù)據(jù)傳輸是正常的,結(jié)束 SYN-SENT 階段。并返回最后一段 TCP 報(bào)文。其中:
- 標(biāo)志位為 ACK,表示“確認(rèn)收到服務(wù)器同意連接的信號(hào)”
- 序號(hào)為 Seq=x+1
表示收到服務(wù)器的確認(rèn)號(hào) Ack,并將其值作為自己的序號(hào)值; - 確認(rèn)號(hào)為 Ack=y+1
表示收到服務(wù)器序號(hào) Seq,并將其值 +1 作為自己的確認(rèn)號(hào) Ack 的值; - 隨后客戶端進(jìn)入 ESTABLISHED 階段。
服務(wù)器收到來自客戶端的“確認(rèn)收到服務(wù)器數(shù)據(jù)”的 TCP 報(bào)文之后,明確了從服務(wù)器到客戶端的數(shù)據(jù)傳輸是正常的。結(jié)束 SYN-SENT 階段,進(jìn)入 ESTABLISHED 階段。
在客戶端與服務(wù)器傳輸?shù)?TCP 報(bào)文中,雙方的確認(rèn)號(hào) Ack 和序號(hào) Seq 的值,都是在彼此 Ack 和 Seq 值的基礎(chǔ)上進(jìn)行計(jì)算的,這樣做保證了 TCP 報(bào)文傳輸?shù)倪B貫性。一旦出現(xiàn)某一方發(fā)出的 TCP 報(bào)文丟失,便無法繼續(xù)"握手",以此確保了"三次握手"的順利完成。
此后客戶端和服務(wù)器進(jìn)行正常的數(shù)據(jù)傳輸。這就是“三次握手”的過程。通過這樣的三次握手,客戶端與服務(wù)端建立起可靠的雙工的連接,開始傳送數(shù)據(jù)。 三次握手的最主要目的是保證連接是雙工的,可靠更多的是通過重傳機(jī)制來保證的。

為什么一定要進(jìn)行三次握手來保證連接是雙工的呢,一次或兩次不行么?舉個(gè)例子:把客戶端比作男孩,服務(wù)器比作女孩。用他們的交往來說明“三次握手”過程:
男孩喜歡女孩,寫了一封信告訴女孩:請(qǐng)和我交往吧。寫完信之后,男孩焦急地等待,因?yàn)椴恢佬拍芊耥樌麄鬟_(dá)給女孩。
女孩收到男孩的情書后,心花怒放,于是給男孩寫了一封回信:我收到你的情書了,我也喜歡你,我愿意和你交往。寫完信之后,女孩也焦急地等待,因?yàn)椴恢阑匦拍芊衲茼樌麄鬟_(dá)給男孩。
男孩收到回信之后很開心,因?yàn)榘l(fā)出的情書女孩收到了,并且從回信中知道了女孩喜歡自己,并且愿意和自己交往。然后男孩又寫了一封信告訴女孩:你的心意和信我都收到了,謝謝你,還有我愛你!
女孩收到男孩的回信之后,也很開心,因?yàn)榘l(fā)出的情書男孩收到了。由此男孩女孩雙方都知道了彼此的心意,之后就快樂地交流起來了。
這就是通俗版的“三次握手”,期間一共往來了三封信也就是“三次握手”,以此確認(rèn)兩個(gè)方向上的數(shù)據(jù)傳輸通道是否正常。
同理對(duì)于 TCP 為什么需要進(jìn)行三次握手,可以這樣理解:為了保證服務(wù)端能收接受到客戶端的信息并能做出正確的應(yīng)答而進(jìn)行前兩次(第一次和第二次)握手,為了保證客戶端能夠接收到服務(wù)端的信息并能做出正確的應(yīng)答而進(jìn)行后兩次(第二次和第三次)握手。
三、為什么要進(jìn)行第三次握手
為了防止服務(wù)器開啟一些無用的連接增加服務(wù)器開銷以及防止已失效的連接請(qǐng)求報(bào)文段突然又傳送到了服務(wù)端產(chǎn)生錯(cuò)誤。
由于網(wǎng)絡(luò)傳輸是有延時(shí)的(要通過網(wǎng)絡(luò)光纖和各種中間代理服務(wù)器),在傳輸?shù)倪^程中,比如客戶端發(fā)起了 SYN=1 創(chuàng)建連接的請(qǐng)求(第一次握手)。
如果服務(wù)器就直接創(chuàng)建了這個(gè)連接并返回包含 SYN、ACK 和 Seq 等內(nèi)容的數(shù)據(jù)包給客戶端,這個(gè)數(shù)據(jù)包因?yàn)榫W(wǎng)絡(luò)傳輸?shù)脑騺G失了,丟失之后客戶端就一直沒有接收到服務(wù)器返回的數(shù)據(jù)包。
客戶端可能設(shè)置了一個(gè)超時(shí)時(shí)間,時(shí)間到了就關(guān)閉了連接創(chuàng)建的請(qǐng)求。再重新發(fā)出創(chuàng)建連接的請(qǐng)求,而服務(wù)器是不知道的,如果沒有第三次握手告訴服務(wù)器“客戶端收得到服務(wù)器響應(yīng)的數(shù)據(jù)”的話,服務(wù)器是不知道“客戶端有沒有接收到服務(wù)器返回的信息”的。這個(gè)過程可理解為:
這樣沒有給服務(wù)器一個(gè)創(chuàng)建還是關(guān)閉連接端口的請(qǐng)求,服務(wù)器的端口就一直開著,等到客戶端因超時(shí)重新發(fā)出請(qǐng)求時(shí),服務(wù)器就會(huì)重新開啟一個(gè)端口連接。那么服務(wù)器上沒有接收到請(qǐng)求數(shù)據(jù)的上一個(gè)端口就一直開著,長(zhǎng)此以往,這樣的端口多了,就會(huì)造成服務(wù)器開銷的嚴(yán)重浪費(fèi)。
還有一種情況是已經(jīng)失效的客戶端發(fā)出的請(qǐng)求信息,由于某種原因傳輸?shù)搅朔?wù)器,服務(wù)器以為是客戶端發(fā)出的有效請(qǐng)求,接收后產(chǎn)生錯(cuò)誤。
所以需要“第三次握手”來確認(rèn)這個(gè)過程,讓客戶端和服務(wù)器能夠及時(shí)地察覺到因?yàn)榫W(wǎng)絡(luò)等一些問題導(dǎo)致的連接創(chuàng)建失敗,這樣服務(wù)器的端口就可以關(guān)閉了不用一直等待。
也可以這樣理解:“第三次握手”是客戶端向服務(wù)器發(fā)送數(shù)據(jù),這個(gè)數(shù)據(jù)就是要告訴服務(wù)器,客戶端有沒有收到服務(wù)器“第二次握手”時(shí)傳過去的數(shù)據(jù)。若發(fā)送的這個(gè)數(shù)據(jù)是“收到了”的信息,接收后服務(wù)器就正常建立 TCP 連接,否則建立 TCP 連接失敗,服務(wù)器關(guān)閉連接端口。由此減少服務(wù)器開銷和接收到失效請(qǐng)求發(fā)生的錯(cuò)誤。
四、TCP四次揮手(Four-Way Wavehand)
所謂的四次揮手即 TCP 連接的釋放(解除)。連接的釋放必須是一方主動(dòng)釋放,另一方被動(dòng)釋放??蛻舳酥鲃?dòng)釋放連接圖解:
揮手之前主動(dòng)釋放連接的客戶端結(jié)束 ESTABLISHED 階段。隨后開始“四次揮手”:
1??首先客戶端想要釋放連接,向服務(wù)器發(fā)送一段 TCP 報(bào)文,其中:
- 標(biāo)記位為 FIN,表示“請(qǐng)求釋放連接”。
- 序號(hào)為 Seq=U。
- 隨后客戶端進(jìn)入 FIN-WAIT-1 階段,即半關(guān)閉階段。并且停止在客戶端到服務(wù)器方向上發(fā)送數(shù)據(jù),但是客戶端仍然能接收從服務(wù)器傳輸過來的數(shù)據(jù)。
注意:這里不發(fā)送的是正常連接時(shí)傳輸?shù)臄?shù)據(jù)(非確認(rèn)報(bào)文),而不是一切數(shù)據(jù),所以客戶端仍然能發(fā)送 ACK 確認(rèn)報(bào)文。
2??服務(wù)器接收到從客戶端發(fā)出的 TCP 報(bào)文之后,確認(rèn)了客戶端想要釋放連接,隨后服務(wù)器結(jié)束 ESTABLISHED 階段,進(jìn)入 CLOSE-WAIT 階段(半關(guān)閉狀態(tài))并返回一段 TCP 報(bào)文,其中:
- 標(biāo)記位為 ACK,表示“接收到客戶端發(fā)送的釋放連接的請(qǐng)求”。
- 序號(hào)為 Seq=V。
- 確認(rèn)號(hào)為 Ack=U+1,表示是在收到客戶端報(bào)文的基礎(chǔ)上,將其序號(hào) Seq 的值 +1 作為本段報(bào)文確認(rèn)號(hào) Ack 的值。
- 隨后服務(wù)器開始準(zhǔn)備釋放服務(wù)器到客戶端方向上的連接。
客戶端收到從服務(wù)器發(fā)出的 TCP 報(bào)文之后,確認(rèn)了服務(wù)器收到了客戶端發(fā)出的釋放連接請(qǐng)求,隨后客戶端結(jié)束 FIN-WAIT-1 階段,進(jìn)入 FIN-WAIT-2 階段。
前"兩次揮手"既讓服務(wù)器知道了客戶端想要釋放連接,也讓客戶端知道了服務(wù)器收到了自己想要釋放連接的請(qǐng)求。于是,可以確認(rèn)關(guān)閉客戶端到服務(wù)器方向上的連接了。
3??服務(wù)器自從發(fā)出 ACK 確認(rèn)報(bào)文之后,經(jīng)過 CLOSED-WAIT 階段,做好了釋放服務(wù)器到客戶端方向上的連接準(zhǔn)備,再次向客戶端發(fā)出一段 TCP 報(bào)文,其中:
- 標(biāo)記位為 FIN,ACK,表示“已經(jīng)準(zhǔn)備好釋放連接了”。注意:這里的 ACK 并不是確認(rèn)收到服務(wù)器報(bào)文的確認(rèn)報(bào)文。
- 序號(hào)為 Seq=W。
- 確認(rèn)號(hào)為 Ack=U+1。表示是在收到客戶端報(bào)文的基礎(chǔ)上,將其序號(hào) Seq 值 +1 作為本段報(bào)文確認(rèn)號(hào) Ack 的值。
隨后服務(wù)器結(jié)束 CLOSE-WAIT 階段,進(jìn)入 LAST-ACK 階段。并且停止在服務(wù)器到客戶端的方向上發(fā)送數(shù)據(jù),但是服務(wù)器仍然能夠接收從客戶端傳輸過來的數(shù)據(jù)。
4??客戶端收到從服務(wù)器發(fā)出的 TCP 報(bào)文,確認(rèn)了服務(wù)器已做好釋放連接的準(zhǔn)備,結(jié)束 FIN-WAIT-2 階段,進(jìn)入 TIME-WAIT 階段,并向服務(wù)器發(fā)送一段報(bào)文,其中:
- 標(biāo)記位為 ACK,表示“接收到服務(wù)器準(zhǔn)備好釋放連接的信號(hào)”。
- 序號(hào)為 Seq=U+1。表示是在收到了服務(wù)器報(bào)文的基礎(chǔ)上,將其確認(rèn)號(hào) Ack 值作為本段報(bào)文序號(hào)的值。
- 確認(rèn)號(hào)為 Ack=W+1。表示是在收到了服務(wù)器報(bào)文的基礎(chǔ)上,將其序號(hào) Seq 值作為本段報(bào)文確認(rèn)號(hào)的值。
隨后客戶端開始在 TIME-WAIT 階段等待 2MSL。
服務(wù)器收到從客戶端發(fā)出的 TCP 報(bào)文之后結(jié)束 LAST-ACK 階段,進(jìn)入 CLOSED 階段。由此正式確認(rèn)關(guān)閉服務(wù)器到客戶端方向上的連接。
客戶端等待完 2MSL 之后,結(jié)束 TIME-WAIT 階段,進(jìn)入 CLOSED 階段,由此完成“四次揮手”。
后“兩次揮手”既讓客戶端知道了服務(wù)器準(zhǔn)備好釋放連接了,也讓服務(wù)器知道了客戶端收到了自己準(zhǔn)備好釋放連接了。于是,可以確認(rèn)關(guān)閉服務(wù)器到客戶端方向上的連接了,由此完成“四次揮手”。
與“三次揮手”一樣,在客戶端與服務(wù)器傳輸?shù)?TCP 報(bào)文中,雙方的確認(rèn)號(hào) Ack 和序號(hào) Seq 的值,都是在彼此 Ack 和 Seq 值的基礎(chǔ)上進(jìn)行計(jì)算的,這樣做保證了 TCP 報(bào)文傳輸?shù)倪B貫性,一旦出現(xiàn)某一方發(fā)出的 TCP 報(bào)文丟失,便無法繼續(xù)"揮手",以此確保了"四次揮手"的順利完成。

把客戶端比作男孩,服務(wù)器比作女孩。通過他們的分手來說明“四次揮手”過程。
- “第一次揮手”:日久見人心,男孩發(fā)現(xiàn)女孩變了,于是決定分手,隨即寫了一封信告訴女孩。
- “第二次揮手”:女孩收到信之后,知道了男孩要和自己分手,立馬給男孩寫了一封回信:分手就分手,給我點(diǎn)時(shí)間,我要把你的東西整理好,全部還給你!男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。隨后等待女孩把自己的東西收拾好。
- “第三次揮手”:過了幾天,女孩把男孩送的東西都整理好了,于是再次寫信給男孩:你的東西我整理好了,快把它們拿走。
- “第四次揮手”:男孩收到女孩第二封信之后,知道了女孩收拾好東西了,可以正式分手了,于是再次寫信告訴女孩:我知道了,這就去拿回來!這里雙方都有各自的堅(jiān)持。女孩自發(fā)出第二封信開始,限定一天內(nèi)收不到男孩回信,就會(huì)再發(fā)一封信催促男孩來取東西!男孩自發(fā)出第二封信開始,限定兩天內(nèi)沒有再次收到女孩的信就認(rèn)為,女孩收到了自己的第二封信;若兩天內(nèi)再次收到女孩的來信,就認(rèn)為自己的第二封信女孩沒收到,需要再寫一封信,再等兩天…..
倘若雙方信都能正常收到,最少只用四封信就能徹底分手!這就是“四次揮手”。
五、為什么建立連接是三次握手,而關(guān)閉連接卻是四次揮手?
TCP 建立連接時(shí)之所以“三次握手”,是因?yàn)樵诘诙巍拔帐帧边^程中,服務(wù)器發(fā)送給客戶端的 TCP 報(bào)文是以 SYN 與 ACK 作為標(biāo)志位的。SYN 是請(qǐng)求連接標(biāo)志,表示服務(wù)器同意建立連接;ACK 是確認(rèn)報(bào)文,表示告訴客戶端,服務(wù)器收到了它的請(qǐng)求報(bào)文。即 SYN 建立連接報(bào)文與 ACK 確認(rèn)接收?qǐng)?bào)文是在同一次“握手”當(dāng)中傳輸?shù)?,所以“三次握手”不多也不少,正好讓雙方明確彼此信息互通。
TCP 釋放連接時(shí)之所以需要“四次揮手”,是因?yàn)?FIN 釋放連接報(bào)文與 ACK 確認(rèn)接收?qǐng)?bào)文是分別由第二次和第三次“握手”傳輸?shù)摹楹谓⑦B接時(shí)一起傳輸,釋放連接時(shí)卻要分開傳輸?
建立連接時(shí),被動(dòng)方服務(wù)器結(jié)束 CLOSED 階段進(jìn)入“握手”階段并不需要任何準(zhǔn)備,可以直接返回 SYN 和 ACK 報(bào)文,開始建立連接。釋放連接時(shí),被動(dòng)方服務(wù)器,突然收到主動(dòng)方客戶端釋放連接的請(qǐng)求時(shí)并不能立即釋放連接,因?yàn)檫€有必要的數(shù)據(jù)需要處理,所以服務(wù)器先返回 ACK 確認(rèn)收到報(bào)文,經(jīng)過 CLOSE-WAIT 階段準(zhǔn)備好釋放連接之后,才能返回 FIN 釋放連接報(bào)文。所以是“三次握手”,“四次揮手”。
六、為什么客戶端在 TIME-WAIT 階段要等 2MSL
為的是確認(rèn)服務(wù)器是否收到客戶端發(fā)出的 ACK 確認(rèn)報(bào)文。
當(dāng)客戶端發(fā)出最后的 ACK 確認(rèn)報(bào)文時(shí),并不能確定服務(wù)器能夠收到該段報(bào)文。所以客戶端在發(fā)送完 ACK 確認(rèn)報(bào)文之后,會(huì)設(shè)置一個(gè)時(shí)長(zhǎng)為 2MSL 的計(jì)時(shí)器。MSL 指的是 Maximum Segment Lifetime:一段TCP報(bào)文在傳輸過程中的最大生命周期。2MSL 即是服務(wù)器發(fā)出為 FIN 報(bào)文和客戶端發(fā)出的 ACK 確認(rèn)報(bào)文所能保持有效的最大時(shí)長(zhǎng)。
服務(wù)器在 1MSL 內(nèi)沒有收到客戶端發(fā)出的 ACK 確認(rèn)報(bào)文,就會(huì)再次向客戶端發(fā)出 FIN 報(bào)文;
- 如果客戶端在 2MSL 內(nèi),再次收到了來自服務(wù)器的 FIN 報(bào)文,說明服務(wù)器由于各種原因沒有接收到客戶端發(fā)出的 ACK 確認(rèn)報(bào)文??蛻舳嗽俅蜗蚍?wù)器發(fā)出 ACK 確認(rèn)報(bào)文,計(jì)時(shí)器重置,重新開始 2MSL 的計(jì)時(shí)。
- 否則客戶端在 2MSL 內(nèi)沒有再次收到來自服務(wù)器的 FIN 報(bào)文,說明服務(wù)器正常接收了 ACK 確認(rèn)報(bào)文,客戶端可以進(jìn)入 CLOSED 階段,完成“四次揮手”。
所以,客戶端要經(jīng)歷時(shí)長(zhǎng)為 2SML 的 TIME-WAIT 階段。這也是為什么客戶端比服務(wù)器晚進(jìn)入 CLOSED 階段的原因。