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
時,表明此報文段中有緊急資料,是高優先順序的資料,應儘快傳送,不用在快取中排隊。該控制位需配合緊急指標使用。舉個例子:我們需要取消一個已經傳送了很長程式的執行,因此使用者從鍵盤發出中斷命令。如果不使用緊急資料,那麼這個指令將儲存在接收 TCP 的快取末尾,只有在所有的資料被處理完畢後這兩個字元才被交付接收方的應用程式,這樣做就無法實現立即中斷。
-
確認 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
。 -
緊急指標:當
URG = 1
時,該欄位才有效。關於緊急指標是指向緊急資料的最後一個位元組還是指向緊急資料最後一個位元組的下一個位元組的爭論。最初的TCP
規範給出了兩種解釋,但Host Requirements RFC
確定指向最後一個位元組是正確的。然而,問題在於大多數的實現(包括源自伯克利的實現)繼續使用錯誤的解釋。所有符合Host Requirements RFC
的實現都是可相容的,但很有可能無法與其他大多數主機正確通訊。
三次握手過程
三次握手(Three-way Handshake)指客戶端和伺服器建立一個TCP連線時,雙方總共需要傳送3個報文段。目的:確認雙方的接收能力和傳送能力是否正常
;同時指定雙方的初始化序列號(ISN)為後面的可靠性傳送做準備
。
剛開始服務端處於監聽狀態,進行三次握手由客戶端主動發起:
-
第一次握手:客戶端給服務端發一個
連線請求報文段
,頭部指明SYN=1
,ACK=0
以及初始化序列號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)
攻擊,攻擊方利用伺服器端的資源是在二次握手時分配的這一特徵進行攻擊。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
緩慢地增大,即每經過一個往返時間 RTT
就把傳送方的擁塞視窗 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演算法。
對稱加密:加解密祕鑰一樣,優點是加解密速度快,適合對大量資料加密;缺點是使用前需要傳輸給另一個使用方,容易洩露。
非對稱加密:分為私鑰和公鑰,私鑰自己儲存無需傳送,公鑰則是公開的,公鑰加密的資訊只有私鑰能解密(反之亦然)。非對稱加密加解密速度慢,只適合少量資料加密。
完整性校驗演算法(hash演算法):同一資料計算結果相同,一旦資料被修改結果就會改變。通常用來檢查資料是否被篡改。
個HTTPS
請求實際上包含了兩次HTTP
傳輸,可以細分為 4 步:
- 客戶端向伺服器發起
HTTPS
請求,連線到伺服器的443
埠。 - 伺服器將自己向
CA
申請的數字證書傳送給客戶端。數字證書包含了公鑰、簽名等資訊。 - 客戶端解析證書並對其進行驗證。如果證書不是可信機構頒佈,或者證書中的域名與實際域名不一 致,或者證書已經過期,就會向訪問者顯示一個警告,由其選擇是否還要繼續通訊。 如果證書沒有問題,客戶端就會從伺服器證書中取出伺服器的公鑰。然後客戶端還會生成一個隨機碼
KEY
,並使用公鑰將其加密。隨後客戶端把加密後的隨機碼KEY
傳送給伺服器,作為後面對稱加密的金鑰。 - 伺服器在收到訊息後使用私鑰解密得到隨機碼
KEY
,到此客戶端和伺服器就已經成功建立了安全連線。接下來就可以用對稱加密進行通訊了。
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
物件。伺服器根據name
為JSESSIONID
的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
資料包組裝成幀,並再相鄰節點 的鏈路上傳送幀。 -
物理層 :實現相鄰節點間位元流的透明傳輸,儘可能遮蔽傳輸介質和通訊手段的差異。