TCP(傳輸層)
TCP報文段頭部

每個 TCP 段都包含源端和目的端的端口號,用於尋找發送方和接收方應用進程。這兩個值加 上 IP 首部中的源端 IP 地址和目的端 IP 地址唯一確定一個 TCP 連接。
首部固定部分各字段意義如下:
-
源端口和目的端口:各占 2 個字節,分別寫入源端口和目的端口。
IP 地址 + 端口號就可以確定一台主機的一個進程地址 -
序號/序列號(Sequense Number,SN):在一個 TCP 連接中傳送的字節流中的每一個字節都按順序編號。該字段表示本報文段所發送的數據的第一個字節的序號。初始序號稱為 Init Sequense Number, ISN(專指TCP三次握手時前兩次握手的報文段中的序號)。
例如,一報文段的序號是 101,共有 100 字節的數據。這就表明:本報文段的數據的第一個字節的序號是 101,最后一個字節的序號是 200。顯然,下一個報文段的數據序號應當從 201 開始,即下一個報文段的序號字段值應為 201。
-
確認號 ack:期望收到對方下一個報文段的第一個數據字節的序號。若確認號為
N,則表明:到序號N-1為止的所有數據都已正確收到。 -
數據偏移(首部長度):它指出
TCP報文段的數據起始處距離TCP報文段的起始處有多遠。這個字段實際上是指出TCP報文段的首部長度。 -
保留:占 6 位,應置為 0,保留為今后使用。
6 個控制位非常重要:
-
緊急位 URG:當
URG = 1時,表明此報文段中有緊急數據,是高優先級的數據,應盡快發送,不用在緩存中排隊。該控制位需配合緊急指針使用。 -
確認 ACK:僅當
ACK = 1時確認號字段才有效,當ACK = 0時確認號無效。TCP規定,在連接建立后所有傳送的報文段都必須把ACK置為 1。 -
推送 PSH:接收方收到
PSH = 1的報文段,就盡快地交付到上層應用進程。而不用等到整個緩存都填滿了后再向上交付。當兩個應用進程進行交互式的通信時,有時發送方的應用進程希望在鍵入一個命令后立即就能收到對方的響應。在這種情況下,發送方可以創建一個報文段並把PSH 置為 1發送出去。 -
復位 RST:當
RST = 1時,表明TCP連接中出現了嚴重錯誤(如由於主機崩潰或其他原因),必須釋放連接,然后再重新建立傳輸連接。 -
同步 SYN:
SYN = 1表示這是一個連接請求或連接確認報文段。當SYN = 1而ACK = 0時,表明這是一個連接請求報文段。對方若同意建立連接,則應在響應的連接確認報文段中使SYN = 1且ACK = 1。 -
終止 FIN:用來釋放一個連接。當
FIN = 1時,表明此報文段的發送方數據已發送完畢,並要求釋放TCP連接。 -
窗口:用於流量控制,指明雙方的窗口大小。
-
校驗和:發送方初始校驗和字段為0,對
TCP 首部(包含12字節的偽首部)和TCP 數據每個16 bit進行二進制反碼的求和,然后重新填入校驗和字段。接收方收到數據后以同樣的方式計算校驗和,但接收方在計算過程中包含了發送方存在首部中的檢驗和,因此,如果傳輸過程中沒有發生任何差錯, 那么接收方計算的校驗和結果應該為全1。舉例:假設發送方計算的校驗和為
10101010。如果傳輸無誤,那么接收方收到時,不包含校驗和字段計算的反碼求和應該為10101010,再加上校驗和字段的反碼(01010101)即為最終的校驗和:11111111。注:偽首部包含:源IP地址、目的IP地址、保留字節(置0)、傳輸層協議號(TCP是6)、TCP報文長度(報頭+數據)。偽首部是為了增加TCP校驗和的檢錯能力:如檢查TCP報文是否收錯了(目的IP地址)、傳輸層協議是否選對了(傳輸層協議號)等。
-
緊急指針:當
URG = 1時,該字段才有效。關於緊急指針是指向緊急數據的最后一個字節還是指向緊急數據最后一個字節的下一個字節的爭論。最初的TCP規范給出了兩種解釋,但Host Requirements RFC確定指向最后一個字節是正確的。然而,問題在於大多數的實現(包括源自伯克利的實現)繼續使用錯誤的解釋。所有符合Host Requirements RFC的實現都是可兼容的,但很有可能無法與其他大多數主機正確通信。也就是說協議的具體的實現是指向緊急數據最后一個字節的下一個字節。
三次握手過程

三次握手(Three-way Handshake)指客戶端和服務器建立一個TCP連接時,雙方總共需要發送3個報文段。目的:確認雙方的接收能力和發送能力是否正常;同時指定雙方的初始化序列號(ISN)為后面的可靠性傳送做准備。
剛開始服務端處於監聽狀態,進行三次握手由客戶端主動發起:
-
第一次握手:客戶端給服務端發一個
連接請求報文段,頭部指明SYN=1,以及初始化序列號ISN(seq=x)。此報文段不能攜帶數據,但要消耗掉一個序號。隨后客戶端進入SYN_SENT(同步發送)狀態。 -
第二次握手:服務端收到客戶端的
連接請求報文段之后,向客戶端發送連接確認報文段,頭部指明SYN=1,ACK=1,確認號(ack)為x+1,並且也選擇一個初始化序列號y。隨后服務器進入SYN_RCVD(同步接收)的狀態。 -
第三次握手:客戶端收到服務端的
連接確認報文段之后,會向服務端回送一個確認報文段,頭部指明ACK=1,確認號ack=y+1,序號seq=x+1,該報文段可以攜帶數據,不攜帶數據則不消耗序號。隨后客戶端進入ESTABLISHED(連接已建立)狀態。待服務器收到客戶端發送的ACK報文段也會進入ESTABLISHED狀態,完成三次握手。
三次握手為什么不能是兩次?
-
首先需要明確:三次握手是為了讓客戶端和服務端確認對方的發送能力以及接受能力都是正常的。
第一次握手:客戶端發送報文段,服務端收到了。
這樣服務端就能得出結論:客戶端的發送能力、服務端的接收能力是正常的。第二次握手:服務端發送報文段,客戶端收到了。
這樣客戶端就能得出結論:服務端的接收、發送能力,客戶端的接收、發送能力是正常的。不過此時服務器並不能確認客戶端的接收能力是否正常。第三次握手:客戶端發送報文段,服務端收到了。
這樣服務端就能得出結論:客戶端的接收、發送能力正常,服務器自己的發送、接收能力也正常。因此,改成兩次握手,服務端不能確定發送端的接收能力是否正常。
-
且可能存在以下情況:客戶端向服務端發送
連接請求報文段,但由於網絡原因滯留在網絡中。客戶端超時重傳了一個新的連接請求報文段,利用新的請求報文,客戶端和服務端成功建立連接並通信,通信完后關閉釋放了連接。但此時舊的(失效的)連接請求報文段重新到達服務端,如果采用兩次握手建立連接那么就會導致服務端建立錯誤的連接。 -
其次兩次握手,就建立連接,會放大
DDOS攻擊。
什么是半連接隊列
服務器第一次收到客戶端的連接請求報文段並回復之后,就會處於SYN_RCVD(同步接收) 狀態,此時雙方還沒有完全建立其連接,服務器會把此種狀態下請求連接放在一個隊列里,我們把這種隊列稱之為半連接隊列。
當然還有一個全連接隊列,就是已經完成三次握手,建立起連接的就會放在全連接隊列中。如果隊列滿了就有可能會出現丟包現象。
ISN(Initial Sequence Number)是固定的嗎?
TCP建立連接時會確定客戶端和服務端的ISN並交換,他們是后序所發送字節數據編號的原點。ISN是通過隨機生成算法生成的,如果ISN是固定的,攻擊者很容易猜出后續的確認號,因此 ISN 是動態生成的。此外,如果相同客戶端和服務端的前后兩次連接的ISN的相同,第一次連接結束后,第二次連接數據傳輸過程中,屬於前一次連接但滯留在網絡中的報文段突然又到達服務端,服務器是沒法區分的。
備注:RFC1948中提出了一個較好的初始化序列號ISN隨機生成算法。ISN = M + F(localhost, localport, remotehost, remoteport)。M是一個計時器,這個計時器每隔4毫秒加1。F是一個Hash算法,根據源IP、目的IP、源端口、目的端口生成一個隨機數值。要保證hash算法不能被外部輕易推算得出,用MD5算法是一個比較好的選擇。
三次握手過程中可以攜帶數據嗎?
第一次、第二次握手不可以攜帶數據,而第三次握手是可以攜帶數據的。
假如第一次握手可以攜帶數據的話,如果有人要惡意攻擊服務器,那他每次都在第一次握手中的 連接請求報文段中放入大量的數據,並瘋狂重發。這會讓服務器花費大量的內存空間來緩存這些報文段,這樣服務器就更容易被攻擊了。
對於第三次握手,此時客戶端已經處於連接狀態,他已經知道服務器的接收、發送能力是正常的了,所以可以攜帶數據是情理之中。
SYN攻擊是什么?
SYN 攻擊是一種典型的 DoS/DDoS(Distributed Denial of Service) 攻擊,建立TCP連接時,攻擊方利用服務器端的資源是在二次握手時分配的這一特征進行攻擊。SYN攻擊就是攻擊端在短時間內偽造大量不存在的IP地址,並向服務端不斷地發送連接請求報文段,服務端則回復連接確認報文段,並等待攻擊端的確認報文段,由於源地址是偽造的,因此服務端需要不斷重發直至超時,這些偽造的連接請求報文段導致大量的請求連接長時間占用半連接隊列,導致正常的連接請求因為隊列滿而被丟棄,從而引起網絡擁塞甚至系統癱瘓。
第三次握手失敗怎么辦?
客戶端收到服務端的連接確認報文段后,其狀態變為ESTABLISHED,並會發送確認報文段給服務端,准備發送數據了。如果此時確認報文段在網絡中丟失,並且服務端超時沒收到確認報文段,那么服務端會重新發送連接確認報文段(第二次握手的報文段)。如果重傳指定次數之后仍然未收到客戶端的確認報文段,服務端將自動關閉這個連接。但是客戶端認為這個連接已經建立,如果客戶端向服務端發數據,服務端將以復位報文段響應,客戶端方能感知到服務端的錯誤。
四次揮手過程

由於客戶端或服務端均可主動發起揮手動作,因此這里稱主動方和被動方。四次揮手(Four-way handshake)指主動方和和被動方斷開 TCP 連接需要發送四個包報文段。揮手前,雙方都處於ESTABLISHED 狀態,假如是客戶端先發起關閉請求,對應過程如下:
- 第一次揮手:客戶端向服務端發送一個
連接釋放報文段,頭部指明FIN=1,序號seq=u。並停止發送數據,主動關閉TCP連接。隨后客戶端進入FIN_WAIT1(終止等待1)狀態,等待服務端的確認。 - 第二次揮手:服務端收到客戶端發來的
連接釋放報文段后,回送確認報文段,頭部指明ACK=1,確認號ack=u+1,序號seq=v,隨后服務端進入CLOSE_WAIT(關閉等待) 狀態。客戶端收到服務端的確認報文段后,進入FIN_WAIT2(終止等待2)狀態,等待服務端發出的連接釋放報文段。 - 第三次揮手:如果服務端也想斷開連接了,和客戶端的第一次揮手一樣,向客戶端發送
連接釋放報文段,頭部指明FIN=1,ACK=1,序號seq=w,確認號ack=u+1,隨后服務端進入LAST_ACK(最后確認)狀態,等待客戶端的確認報文段。 - 第四次揮手:客戶端收到
連接釋放報文段之后,同樣向服務端發出確認報文段,頭部指明ACK=1,seq=u+1,ack=w+1,此時客戶端進入TIME_WAIT狀態。服務端收到客戶端的確認報文段之后,進入CLOSED狀態。客戶端必須經過2*MSL后才進入CLOSED狀態。此時TCP連接已經完全釋放。
建立連接只需要握手三次,關閉連接時需要揮手四次呢?
其實在 TCP 第二次握手的時候,服務端發送的 連接確認報文段 將一個 ACK 和一個 SYN 合並到一起發送給服務端,所以減少了一次包的發送,三次便完成握手。對於四次揮手,因為 TCP 是全雙工通信,在主動方發送連接釋放報文段后,被動方可能還要發送數據,不能立即關閉被動方到主動方的數據通道,所以被動方不能將確認報文段 與 連接釋放報文段合並回送給主動方。只能先發送將確認報文段回送給主動方,然后待被動方無需發送數據時再回送 連接釋放報文段,所以四次揮手必須使用四次數據包交互。
四次揮手時,主動方等待2MSL的意義?
MSL是
Maximum Segment Lifetime的英文縮寫,指“報文段在網絡中最大生存時間”,超過這個時間報文段將被丟棄。
-
保證主動方發送的最后一個
確認報文段能夠到達被動方。這個
確認報文段有可能丟失,使得處於LAST-ACK(最后確認)狀態的被動方收不到該報文段,被動方超時重傳連接釋放報文段,而主動方能在2MSL時間內收到這個重傳的連接釋放報文段,接着主動方重傳一次確認報文段,重啟2MSL計時器,最后雙方都進入到CLOSED狀態。若主動方發完確認報文段后立即釋放連接,被動方在超時未收到確認報文段的情況就不能正常處理,就導致被動方無法正常進入到CLOSED狀態。 -
防止“已失效的連接請求報文段”出現在新連接中。
主動方發送完最后一個
確認報文段,再經過2MSL,就可以使本次連所產生的所有報文段都從網絡中消失,使下一個新的連接中不會出現舊的連接請求報文段。
其他
如果已經建立了連接,但是客戶端突然出現故障了怎么辦?
TCP設有一個保活計時器,服務器每收到一次客戶端的TCP報文段后都會重新復位這個計時器,時間通常是設置為2小時。客戶端如果出現故障若,導致服務端兩小時都沒有收到客戶端的任何數據,服務器就會每隔75秒鍾發送一個探測報文段,若一連發送10個探測報文段仍然沒反應,服務器就認為客戶端出了故障,接着就關閉連接。
TCP依靠哪些機制來保證可靠傳輸?
-
校驗和:
TCP通過校驗和檢測數據在傳輸過程中是否發生改變,如果收到的報文段的校驗和有差錯,報文段將被丟棄。 -
序列號和確認應答:
TCP給發送的每一個報文段中都有序號字段,每次接收方收到數據后,都會對傳輸方進行確認應答,即發送確認報文段(ACK),其中的確認號告訴發送方成功接收了哪些數據以及下一次請求的數據從哪里開始發。除此之外,接收方可以根據序列號對數據包進行排序,把有序數據傳送給應用層,並丟棄重復的數據。 -
超時重傳:當
TCP發出一個報文段后,它將啟動一個定時器,等待接收端發回的確認。如果超過定時器超時還沒有收到確認,發送方將重發這個報文段。 -
約定最大報文段長度(MSS):在建立
TCP連接的時候,雙方可以在頭部選項字段中約定最大報文段長度作為發送的單位,理想的情況下是該長度的數據剛好不被網絡層分片。 -
流量控制:
TCP通過滑動窗口機制實現流量控制,窗口(緩沖區)的大小就是發送方在無需等待確認報文段的情況下還能發送的最大數據量。TCP通過窗口大小來協調端對端的發送速度,確保接收端來得及接收,從而盡可能減少丟包。 -
擁塞控制:通過擁塞控制算法(慢開始、擁塞避免、快重傳、快恢復),根據全局網絡的擁塞程度來調整擁塞窗口的大小,改善網絡擁塞程度,從而盡可能減少丟包。
備注:發送窗口的大小等於Min(接收窗口, 擁塞窗口),因此是兩種流量控制和擁塞控制的共同作用。
ARQ協議與滑動窗口機制的關系?
自動重傳請求 ( Automatic Repeat-reQuest , ARQ )是 OSI模型 中 數據鏈路層 和 傳輸層 的錯誤糾正協議之一。其利用確認和超時這兩個機制,可以在不可靠服務的基礎上實現可靠的信息傳輸。ARQ協議分等停ARQ協議和連續ARQ協議,連續ARQ協議采用了滑動窗口機制,后者又可分為后退N步協議和選擇重傳協議。
擁塞控制有哪些算法?
擁塞控制算法:慢開始、擁塞避免、快重傳、快恢復。這些算法會根據網絡不同的擁塞狀況來搭配使用。
慢開始算法:在一開始不清楚網絡擁塞程度時,避免一開始就向網絡中注入大量數據,由小到大逐漸增大擁塞窗口數值。cwnd(擁塞窗口) 初始值設為為 1,每經過一個傳輸輪次(transmission round),cwnd 加倍。(慢開始並不是指cwnd增長慢)。當擁塞窗口達到慢開始門限值 ssthresh,改用擁塞避免算法。(當cwnd = ssthresh時,既可使用慢開始算法,也可使用擁塞避免算法)。

擁塞避免算法: 擁塞避免算法的思路是讓 cwnd 緩慢地增大,即每經過一個傳輸輪次就把發送方的擁塞窗口 cwnd 加1,而不是加倍。這樣,擁塞窗口 cwnd 按線性規律緩慢增長,比慢開始算法的擁塞窗口增長速率緩慢得多。
無論在慢開始階段還是在擁塞避免階段,只要發送方判斷網絡出現擁塞(計時器超時,未收到確認),就要把慢開始門限 ssthresh 設置為出現擁塞時的發送窗口值的一半(但不能小於2)。然后把擁塞窗口 cwnd 重新設置為 1,執行慢開始算法。

快重傳算法:快重傳算法要求接收方在收到一個失序的報文段后就立即發出重復確認而不要等到自己發送數據時捎帶確認。發送方只要一連收到三個重復確認就應當立即重傳對方尚未收到的報文段,而不必繼續等待設置的重傳計時器時間到期。(以便發送方及早知道丟失發生,及早進行重傳)。與快重傳配合使用的還有快恢復算法。

快恢復算法:當發送方連續收到三個重復確認時,把 ssthresh 門限減半。考慮到如果網絡出現擁塞的話就不會收到好幾個重復的確認,所以發送方認為現在網絡可能沒有出現擁塞。所以此時不執行慢開始算法,而是將cwnd設置為ssthresh的大小,然后執行擁塞避免算法。

流量控制與擁塞控制有何不同?
流量控制:采用端對端的機制,接收端通過窗口字段告知發送端自己的接收能力,進而協調發送端的發送速度,避免接收端來不及接收而丟包。
擁塞控制:采用面向全局的機制,根據網絡的擁塞程度來改變擁塞窗口,進而協調主機向網絡中注入數據的速度,改善網絡擁塞程度,從而盡可能減少丟包。
TCP 和 UDP 的區別?
| 類型 | 傳輸可靠性 | 是否面向連接 | 是否支持多播,廣播 | 傳輸形式 | 資源占用 | 首部長度(字節) | 應用場景 |
|---|---|---|---|---|---|---|---|
| TCP | 可靠 | 是 | 否 | 面向字節流 | 多 | 20 - 60 | 文件,郵件傳輸 |
| UDP | 不可靠 | 否 | 是 | 面向報文段 | 少 | 8 | 即時通訊,直播等 |
TCP 提供可靠服務,在傳送數據之前必須先建立連接,數據傳送結束后要釋放連接;UDP與之相反,只盡最大努力交付。
TCP不提供廣播或多播服務;UDP則提供。
TCP是面向字節流的;而UDP是面向報文段的。
TCP 要提供可靠的服務,建立連接,釋放連接,加之確認、窗口、重傳、流量控制、擁塞控制、定時器等機制都會占用更多的系統資源,同時導致協議頭部增大(20 - 60 字節);UDP則占用較少系統資源,協議頭部也更小(僅 8 字節)。
TCP提供可靠服務,故使用在文件傳輸、郵件傳輸等場景;雖然 UDP 不提供可靠交付,但在某些情況下 UDP 確是一種最有效的工作方式,如即時通訊,直播等場景。
什么是 TCP 粘包問題?
TCP粘包就是指發送方應用層交給TCP發送的若干數據包經過TCP傳輸到達接收方時合並粘成了一個數據包,出現粘包的原因是多方面的,可能是來自發送方,也可能是來自接收方。
造成TCP粘包的原因?
-
發送方原因
TCP默認使用Nagle算法,當應用層交付給TCP發送的數據包過於小時,發送方會收集了多個較小的數據包進行合並發送,這將會發生粘包。 -
接收方原因
TCP發送方發送數據很快,接收方TCP緩沖區收到大量數據,但應用層取出數據的速度又太慢,造成多個數據包被緩存,應用層就有可能讀取到多個首尾相接粘到一起的數據包。
什么時候需要處理粘包問題?
- 如果發送方發送的多個數據包本來就是同一塊數據的不同部分就不需要處理粘包現象。
- 如果多個數據包毫不相干,甚至是並列關系,那么這個時候就一定要處理粘包現象了。
如何處理粘包問題?
在應用層進行處理。如:
- 在應用層交給
TCP的每個數據包頭部都添加長度字段,接收方應用層讀取數據時根據數據包頭部長度字段循環讀取相應長度的內容; - 將應用層交給
TCP的每個數據包的首、尾分別添加開始符、結束符。
HTTP(應用層)
HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。HTTP是一個基於TCP/IP通信協議來傳遞數據(HTML,圖片等文件,以及查詢結果等)。
主要特點如下:
-
簡單快速:客戶向服務器請求服務時,只需傳送請求方法和路徑。請求方法常用的有
GET、HEAD、POST。每種方法規定了客戶與服務器聯系的類型不同。由於HTTP協議簡單,使得HTTP服務器的程序規模小,因而通信速度很快。 -
靈活:
HTTP允許傳輸多種類型的數據對象。正在傳輸的類型由Content-Type加以標記。 -
無連接:無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並應答后,即斷開連接。采用這種方式可以節省傳輸時間。
-
無狀態:
HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味着如果后續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。 -
支持
B/S及C/S模式
HTTP 協議由哪幾部分組成?
-
請求協議信息由 4 部分組成:請求行、請求頭、空行、請求體
-
響應協議信息也由 4 部分組成:狀態行、響應頭、空行、響應體
使用
curl命令查看協議詳情:
HTTP狀態碼?
HTTP 狀態碼由三個十進制數字組成,第一個數字定義了狀態碼的類型。HTTP 狀態碼共有 5 種類型:1xx, 2xx, 3xx, 4xx, 5xx。類型解釋以及部分常見狀態碼如下:
-
1XX (Informational): 接收的請求正在處理100 Continue:表明請求到目前為止都處理的很正常,客戶端可以繼續發送請求或者忽略這個響應。 -
2XX (Success): 請求正常處理完畢
200 OK : 表示成功處理了請求。
3XX (Redirection): 需要進行附加操作以完成請求
301 Moved Permanently :永久性重定向。
302 Found :臨時性重定向。
4XX (Client Error): 服務器無法處理請求
403 Forbidden :請求被服務器拒絕。
404 Not Found : 服務器找不到請求的網頁。
5XX (Server Error): 服務器處理請求出錯
500 Internal Server Error :服務器正在執行請求時發生錯誤。
狀態碼 301 和 302 的區別?
301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼后會自動跳轉到一個新的URL地址,這個地址可以從響應頭部字段Location中獲取(用戶看到的效果就是他輸入的地址A瞬間變成了另一個地址B)
301: 表示永久重定向。該狀態碼表示請求的資源已被分配了新的 URI,以后應使用資源現在所指的 URI。也就是說,如果已經把資源對應的 URI保存為書簽了,這時瀏覽器會按 Location 字段提示的 URI 重新保存。
302: 表示臨時重定向。該狀態碼表示請求的資源已被分配了新的 URI,希望用戶(本次)能使用新的 URI 訪問。和 301 狀態碼相似,但 302 狀態碼代表的資源不是被永久移動,只是臨時性質的。換句話說,已移動的資源對應的URI 將來還有可能發生改變。比如,用戶把 URI 保存成書簽,但不會像 301 狀態碼出現時那樣去更新書簽,而是仍舊保留返回 302 狀態碼的頁面對應的 URI。
Forward和Redirect的區別?
Forward:客戶端發出的請求被服務器內部進行轉發,瀏覽器地址欄依然是之前的URL。就如 SpringMVC 中,所有的請求都由 DispatcherServlet處理后再在服務器內部進行派發。
Redirect:實際是兩次HTTP請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另外一個URL發出請求,從而達到轉發的目的。
HTTP 請求方法了解哪些?
HTTP/1.0 定義了三種請求方法:GET, POST 和 HEAD 方法。
| 方法 | 描述 |
|---|---|
| GET | 最常用的方法之一,用於請求服務器響應某個資源,不應當對系統資源進行改變。 |
| POST | 最常用的方法之一,用於將數據(表單等)提交至服務器以創建新的資源。 |
| HEAD | HEAD 方法與 GET 方法的行為很類似,但服務器在響應中只返回首部,這就允許客戶端在未獲取實際資源的情況下,根據首部信息對資源進行檢查。 |
HTTP/1.1新增了:PUT、PATCH、DELETE、CONNECT、OPTIONS、TRACE 共5種HTTP請求方法。
| 方法 | 描述 |
|---|---|
| PUT | 用於將數據提交至服務器以更新之前存在的資源。 |
| PATCH | 是對 PUT 方法的補充,用來對已知資源進行局部更新;當資源不存在時,PATCH會創建一個新的資源。 |
| DELETE | 請求服務器刪除指定的資源。 |
| CONNECT | HTTP/1.1 協議中預留給能夠將連接改為管道方式的代理服務器。 |
| OPTIONS | 請求服務器告知其支持的各種功能。 |
| TRACE | 請求服務器回顯其收到的請求,主要用於測試或診斷。 |
備注:HTTP規范定義了以上方法的行為,但實際開發中可以不遵守。例如:在GET請求對應的接口中去更新資源,將會給自己帶來麻煩。
HTTP冪等性了解嗎?
在編程領域,對於同一個系統,在同樣條件下,一次請求和重復多次請求對服端資源的影響是一致的,就稱該操作為冪等的。
HTTP常見冪等方法:GET、PUT、DELETE、
HTTP常見非冪等方法:POST、PATCH
解釋:
PUT:第一次和第N次請求對服務端資源的影響是相同的,所以是冪等的。例如將id為1234的賬戶金額改為1000,多次調用對系統資源產生的影響是一致的。
DELETE:第一次和第N次請求對服務端資源的影響是相同的,所以是冪等的。假如存在一個刪除 id 為 1234 的賬戶的接口,第一次請求時會刪除,而后面所有請求的時候由於系統中已經沒有該資源了,所以第一次和后面的請求對服務端資源的影響( id 為 1234 的資源不再存在)是相同的。
PATCH: URI 對應的資源不存在時服務端可以創建一個新資源,因此兩次請求對服務端資源的影響可能會不同。並且服務端可以根據請求參數,動態的計算出某個值,例如每次請求后資源的某個參數減1,所以多次調用,資源會有不同的變化。綜上,PATCH方法是非冪等的。
更多:聊聊開發中冪等性問題
了解REST風格嗎?
REST是一種架構風格,即Representational State Transfer的縮寫,譯為"表現層狀態轉化"。REST的原則不僅僅適用於HTTP協議,但由於REST的應用場景絕大部分是WEB應用,故以下討論都基於HTTP。
資源是網絡上的一個實體,或者說是網絡上的一個具體信息,一個資源可以被URI唯一標識。因此,表現層可以理解為資源的一種具體表現,如:文本文件、html文件等等。狀態轉化指客戶端和服務端的交互過程中通過HTTP協議提供的4個動作(GET用來獲取資源,POST用來新建資源,PUT用來更新資源,DELETE用來刪除資源。)對服務器資源進行操作,從而實現"表現層狀態轉化"。
備注:而RESTful API就是符合REST風格的API
GET 和 POST 的區別?
- 從功能上講,
GET一般用來從服務器上獲取資源,POST一般用來在服務器上新增資源; - 從
REST服務角度上說,GET是冪等的,而POST不是冪等的; - 從請求參數形式上看,
GET請求的數據會附在URL之后,POST請求會把提交的數據放置在是HTTP請求報文的請求體中; - 就安全性而言,
POST的安全性要比GET的安全性高,因為 GET 請求提交的數據將明文出現在URL上,而且POST請求參數則被包裝到請求體中,相對更安全; - 從請求的大小看,
GET請求的長度受限於瀏覽器或服務器對URL長度的限制,允許發送的數據量比較小,而POST請求理論上是沒有大小限制。
怎么知道 HTTP 的報文長度?
當傳輸的是靜態文件時,服務端能夠很清楚的知道將要響應內容的大小,可以通過響應頭中的Content-Length 域來告訴客戶端報文的長度。如果服務端預先不知道將要響應內容的大小(動態生成的頁面)就需要在響應頭中指明 Transfer-Encoding: chunked 。表示響應體是使用chunked分塊方式拼接成的,不需要Content-Length指明長度。每一個分塊包含十六進制的長度值和數據,最后一個分塊長度值為0,表示實體結束,客戶端可以以此為標志確認數據已經接收完畢。(這些是HTTP1.1的內容,Content-Length字段不是必需的,因為瀏覽器發現服務器關閉了TCP連接,就表明收到的數據包已經全了)。
Keep-Alive(長連接) 和 非 Keep-Alive 區別?
可以通過請求頭或響應頭中的Connection域查看是否是Keep-Alive。
短連接:在HTTP/1.0中默認使用短連接(也支持長連接,得手動設置Connection: keep-alive)。客戶端每個HTTP請求和響應都會開啟和關閉一個單獨的TCP連接。
長連接: 而從HTTP/1.1起,默認使用長連接。同一個客戶端和服務端之間的連續的多個HTTP請求和響應可以通過一個TCP連接來完成。但是一個長連接也不是一直保持,客戶端在最后一個請求時,發送Connection: close,明確要求服務器關閉TCP連接,也可以通過 keep-alive timeout 參數來設置。
HTTP1.0、HTTP1.1、HTTP2的主要變化?
HTTP1.1變化:
長連接:HTTP1.0 默認是短連接,HTTP1.1 默認支持長連接,且引入了流水線技術(pipelining)。不僅多個請求可以復用同一個TCP連接,並且同一個TCP連接里面,客戶端可以同時發送多個請求。這樣就進一步改進了HTTP協議的效率。(流水線方式會存在"隊頭阻塞":如果第一個請求被阻塞,即使后到的請求已經處理完畢,響應時依然要按請求的順序依次響應)。
寬帶和網絡連接優化:HTTP1.0 會存在一些性能浪費,每次請求都返回整個對象,即使只需要對象的一部分。HTTP1.1則可以通過設置range頭域,僅請求返回資源的某一部分,也就是返回碼為206(Partial Content)的時候,這對於性能優化很有必要。
引入Host頭域:HTTP1.1 添加了Host頭域,請求頭如果沒指定Host,則返回404。在HTTP1.0 中認為每個IP地址都只屬於一台服務器,因此,請求消息中的URL並沒有傳遞主機名。但隨着虛擬主機技術的發展,在一台物理主機上可以存在多個虛擬主機,並且它們共享一個IP地址,僅靠IP地址無法區分請求的是哪個虛擬主機,故HTTP1.1加上了Host頭域來區分。
更多:HTTP中的Host字段
HTTP2 的變化:
二進制:HTTP1.X (頭信息肯定是文本(ASCII編碼),數據體可以是文本,也可以是二進制)的協議解析是基於文本格式,而HTTP2(頭信息和數據體都是二進制,並且統稱為"幀"(frame):頭信息幀和數據幀)的協議解析是二進制格式,解析更加高效。
多路復用(Mutiplexing) : 可以復用TCP連接,在一個連接里,客戶端和瀏覽器都可以同時發送多個請求或回應,而且不用按照順序一一對應,這樣就避免了"隊頭堵塞"
header壓縮: HTTP1.X 協議不帶有狀態,每次請求都必須附上所有信息。所以,請求的很多字段都是重復的,比如Cookie和User Agent,一模一樣的內容,每次請求都必須附帶,這會浪費很多帶寬,也影響速度。HTTP2對這一點做了優化,引入了頭信息壓縮機制(header compression)。一方面,頭信息使用gzip或compress壓縮后再發送;另一方面,客戶端和服務器同時維護一張“首部表”來跟蹤和存儲之前發送的頭域(鍵-值對),對於不變的域,不再通過每次請求和響應發送;通信期間幾乎不會改變的通用域鍵(User Agent、Accept等等) 只需發送一次。
服務端推送(server push): 允許服務器未經請求,主動向客戶端發送資源,這叫做服務器推送。常見場景是客戶端請求一個網頁,這個網頁里面包含很多靜態資源。正常情況下,客戶端必須收到網頁后,解析HTML源碼,發現有靜態資源,再發出靜態資源請求。其實,服務器可以預測到客戶端請求網頁后,很可能會再請求靜態資源,所以就主動把這些靜態資源隨着網頁一起發給客戶端了。
更多:一篇文章讀懂 HTTP1.0 HTTP1.1 HTTP2.0 HTTPS
HTTP 和 HTTPS 的主要區別?
端口:HTTP協議端口為80,HTTPS協議端口為443;
安全性:HTTP信息是明文傳輸;而HTTPS協議的信息是經過SSL/TLS協議加密后傳輸的。( TLS (Transport Layer Security,傳輸層安全協議) 是 SSL (Secure Socket Layer,安全套接字層)的升級版)。
數字證書:HTTPS協議需要到 CA (Certificate Authority)機構申請數字證書,絕大多數需要花錢申請。
響應速度和資源消耗:HTTPS 相比 HTTP 在 TCP 之上多了 SSL/TLS 協議,因此響應速度會更慢,資源消耗會更多。
HTTPS 的工作過程?
前置:SSL/TLS中使用了非對稱加密,對稱加密,
HASH算法同時借助了CA機構及其頒發的數字證書。對稱加密:一個秘鑰,既可以加密也可以解密,優點是加解密速度快,適合對大量數據加密;缺點是使用前需要傳輸給另一個使用方,容易泄露。
非對稱加密:分為私鑰和公鑰,私鑰自己保存無需發送,公鑰則是公開的,公鑰加密的信息只有私鑰能解密(反之亦然)。非對稱加密加解密速度慢,只適合少量數據加密。
完整性校驗算法(
hash算法):同一數據計算結果相同,一旦數據被修改結果就會改變。通常用來檢查數據是否被篡改。數字簽名:可以驗證數據是否為意料中的對象所發出的,二是數據是否被篡改。數字簽名是指發送方使用私鑰將數據的
hash值(數據摘要)進行加密后得到的結果。發送方發送數據時,將數字簽名和數據一同發給接收方;接收方收到數據后使用hash算法也得到了一個數據摘要,同時使用公鑰對發送方的數字簽名進行解密,解密成功得到原數據摘要,兩個數據摘要相同則說明數據沒有被篡改,否則說明數據被篡改。
CA(Certification Authority,證書頒發機構):證書頒發機構負責頒發數字證書,同時他自己有一對公鑰和私鑰,公鑰被提前安裝在各個操作系統當中,私鑰自己保存。數字證書:數字證書包括證書頒發機構,證書有效期,公鑰,主題(證書是頒發給誰了,一般是個人或公司名稱或機構名稱或公司網站的網址),指紋(對證書前面的明文內容使用指紋算法后得到)以及指紋算法(哈希算法),簽名(對指紋使用
CA的私鑰加密得到)以及簽名算法。
HTTPS請求實際上包含了兩次HTTP傳輸,可以細分為 4 步:
- 客戶端向服務器發起
HTTPS請求,發送自己支持的TLS版本、加密算法集以及一個隨機碼R1。 - 服務器確定
TLS版本和加密算法,連同數字證書和隨機碼R2一同發給客戶端。 - 客戶端驗證數字證書,先使用
CA公鑰對證書簽名解密得到原來的指紋信息,並根據證書明文內容結合指紋算法重新計算一份指紋,對比指紋是否一致,以此驗證證書來源和完整性;並驗證證書是否過期以及域名是否與請求域名一致。證書驗證不通過則給出相應提示。 證書驗證通過后,客戶端生成隨機碼R3並使用證書中服務器的公鑰進行加密然后發送給服務端。同時使用算法根據隨機碼R1、R2和R3生成加密通信數據使用的對稱加密秘鑰。 - 服務器在收到消息后使用私鑰解密得到隨機碼
R3,同時利用相同算法根據隨機碼R1、R2和R3生成秘鑰,至此雙方都得到了用於加密通信數據的對稱加密秘鑰。
注:如果HTTPS每次重連都要重新握手確定傳輸秘鑰,就會很費時,可以進行優化。服務器會為每個瀏覽器維護一個session對象並保存傳輸秘鑰,在TLS握手階段服務器構造name為sessionid的cookie傳給瀏覽器,之后瀏覽器每次請求都會攜帶sessionid,服務器會根據sessionid找到相應的傳輸密鑰,這樣就不必要每次重新制作、傳輸密鑰了!
Cookie是什么?
HTTP Cookie(也叫 Web Cookie或瀏覽器 Cookie)是服務器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器下次向同一服務器再發起請求時被攜帶並發送到服務器上。通常可以用於個性化設置,瀏覽器行為跟蹤。
Session是什么?
由於HTTP協議是無狀態的協議,所以服務器需要記錄用戶狀態時就需要借助Session機制。目前Session常見實現要借助Cookie,即服務器端創建一個Session對象,同時會創建一個特殊的Cookie對象(name為"JSESSIONID",value為Session對象的ID),然后將該Cookie對象發送至瀏覽器。當瀏覽器端發送第N(N>1)次請求到同一服務器時就會攜帶該name為JSESSIONID的Cookie對象。服務器根據Cookie的value(sessionId)去查詢對應Session對象,從而區分不同用戶。(Session對象默認存活30分鍾)
Cookie和Session的區別?
- 作用范圍不同,
Cookie保存在客戶端(瀏覽器),Session保存在服務器端。 - 存取方式的不同,
Cookie只能保存ASCII編碼的字符,Session可以存任意數據類型,一般情況下我們可以在Session中保持一些常用變量信息,比如說商品ID,商品數量(購物車場景)等。 - 有效期不同,
Cookie可設置為長時間保持,比如我們經常使用的默認登錄功能,Session一般失效時間較短,客戶端關閉或者Session超時都會失效(Session對象默認存活30分鍾)。 - 隱私策略不同,
Cookie存儲在客戶端,比較容易遭到不法獲取,早期有人將用戶的登錄名和密碼 存儲在Cookie中導致信息被竊取;Session存儲在服務端,安全性相對Cookie要好一些。 - 存儲大小不同, 單個
Cookie保存的數據量<= 4KB;對於Session來說並沒有上限,但出於對服務器端的性能考慮,Session內不要存放過多的東西,並且應設置Session刪除機制。
在瀏覽器中輸入 URL 地址到顯示主頁的過程?
- 首先根據
URL進行域名解析,得到對應IP地址。解析時,首先查看瀏覽器DNS緩存是否命中,沒有的話再查看操作系統DNS緩存(hosts文件)是否命中,如果再沒有命中就會借助域名服務器進行解析。 - 位於應用層的瀏覽器封裝好
HTTP請求報文后交給傳輸層的TCP協議。 TCP協議根據IP地址向服務器的80端口發起三次握手以建立TCP連接,隨后將HTTP報文作為自己的數據部分封裝到TCP報文段中發送出去。- 服務器上的
TCP協議收到TCP報文段后進行拆包得到HTTP請求報文,HTTP請求報文隨后被應用層的服務器程序讀取、解析和處理后,按照之前類似步驟響應數據給瀏覽器。 - 瀏覽器得到
HTTP響應報文后進行解析,渲染並顯示給用戶。
計算機分層模型
- OSI 七層模型:大而全,但是比較復雜、而且是先有了理論模型,沒有實際應用。
- TCP/IP 四層模型:是由實際應用發展總結出來的,從實質上講,
TCP/IP只有最上面三層,最下面一 層沒有什么具體內容,TCP/IP參考模型沒有真正描述這一層的實現。 - 五層模型:五層模型只出現在計算機網絡教學過程中,這是對七層模型和四層模型的一個折中,既 簡潔又能將概念闡述清楚。
三種模型以及對應層次關系如下:

OSI七層網絡體系結構各層的主要功能:
-
應用層:為應用程序提供交互服務。在互聯網中的應用層協議很多,如域名系統
DNS,支持萬維網 應用的HTTP協議,支持電子郵件的SMTP協議等。 -
表示層:主要負責數據格式的轉換,如加密解密、轉換翻譯、壓縮解壓縮等。
-
會話層:負責在網絡中的兩節點之間建立、維持和終止通信,如服務器驗證用戶登錄便是由會話層 完成的。
-
運輸層:有時也譯為傳輸層,向主機進程提供通用的數據傳輸服務。該層主要有以下兩種協議:
-
TCP:提供面向連接的、可靠的數據傳輸服務; -
UDP:提供無連接的、盡最大努力的數據傳輸服務,但不保證數據傳輸的可靠性。
-
-
網絡層:選擇合適的路由和交換結點,確保數據及時傳送。主要包括
IP協議。 -
數據鏈路層:數據鏈路層通常簡稱為鏈路層。將網絡層傳下來的
IP數據包組裝成幀,並再相鄰節點 的鏈路上傳送幀。 -
物理層 :實現相鄰節點間比特流的透明傳輸,盡可能屏蔽傳輸介質和通信手段的差異。
