長連線: Http1.1支援長連線和請求的流水線處理,在一個TCP連線上可以傳送多個HTTP請求和響應,減少建立和關閉連線的消耗和延遲,在HTTP1.1中預設開啓長連線keep-alive,一定程度上彌補了HTTP1.0每次請求都要建立連線的缺點。HTTP1.0需要使用keep-alive參數來告知伺服器端要建立一個長連線。
節約頻寬: HTTP1.0中存在一些浪費頻寬的現象,例如用戶端只是需要某個物件的一部分,而伺服器卻將整個物件傳送過來,並且不支援斷點續傳功能。HTTP1.1支援只發送header資訊(不包括body資訊),如果伺服器認爲用戶端有許可權請求伺服器,則返回100,用戶端接收到100纔開始把請求的body發送到伺服器;如果返回401,用戶端就可以不用發送請求body了,節約頻寬。
HOST域: 在HTTP1.0中認爲每台伺服器都系結一個唯一的IP地址,因此,請求訊息中的URL並沒有傳遞主機名,HTTP1.0沒有host域。隨着虛擬主機技術的發展,在一臺物理伺服器上可以存在多個虛擬主機,並且它們共用一個IP地址。HTTP1.1的請求訊息和響應訊息都支援host域,且請求訊息中如果沒有host域會報告一個錯誤。
**快取處理:**在HTTP1.0中主要使用header裡的If-Modified-Since,Expires來作爲快取判斷的標準,HTTP1.1則引入了更多的快取控制策略,例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供選擇的快取頭來控制快取策略。
錯誤通知的管理: 在HTTP1.1中新增了24個錯誤狀態碼,如409(Conflict)表示請求的資源與資源的當前狀態衝突;410(Gone)表示伺服器上的某個資源被永久性地刪除了。
多路複用: HTTP2.0使用了多路複用的技術,做到同一個連線併發處理多個請求,而且併發請求的數量比HTTP1.1大了好幾個數量級。HTTP1.1也可以多建立幾個TCP連線,來支援處理更多併發的請求,但是建立TCP連線本身也是有開銷的。
頭部數據壓縮: 在HTTP1.1中,HTTP請求和響應都是由狀態行、請求/響應頭部、訊息主體三部分組成。一般而言,訊息主體都會經過gzip壓縮,或者本身傳輸的就是壓縮過後的二進制檔案,但狀態行和頭部卻沒有經過壓縮,直接以純文字傳輸。隨着Web功能越來越複雜,每個頁面產生的請求數也會越來越多,導致消耗在頭部的流量越來越多,尤其每次都要傳輸UserAgent,Cookie這類不會頻繁變動的內容,完全是一種浪費。HTTP1.1中不支援header部分數據的壓縮,HTTP2.0使用HPACK演算法對header的數據進行壓縮,這樣數據體積小了,在網路上傳輸就會很快。
伺服器推播: 伺服器端推播是一種在用戶端請求之前發送數據的機制 機製。網頁使用了許多資源:HTML、樣式表、指令碼、圖片等等。在HTTP1.1中這些資源每一個都必須明確地請求,這是一個很慢的過程。瀏覽器從獲取HTML開始,然後解析和評估頁面的時候,增量地獲取更多的資源。因爲伺服器必須等待瀏覽器做每一個請求,網路經常處於空閒和未充分使用的狀態。
爲了改善延遲,HTTP2.0引入了server push,它允許伺服器端推播資源給瀏覽器,在瀏覽器明確地請求之前,免得用戶端再次建立連線發送請求到伺服器端獲取。這樣用戶端可以直接從本地載入這些資源,不用再通過網路。
三次握手其實就是指建立一個TCP連線,需要用戶端和伺服器端總共發送3個包。進行3次握手的主要作用就是爲了確認雙方的接收能力和發送能力是否正常、指定自己的初始化序列號爲後面的可靠性傳送做準備。實質上其實就是連線伺服器指定埠,建立TCP連線,並同步連線雙發的序列號和確認號,交換TCP視窗大小資訊。
剛開始時用戶端處於Closed狀態,伺服器端處於Listen狀態。
進行3次握手:
1、第一次握手: 用戶端給伺服器端發送一個SYN報文,並指明用戶端的初始序列號爲X,此時用戶端處於SYN_SENT狀態。
2、第二次握手: 伺服器端接收到用戶端的SYN報文後,會以自己的SYN報文作爲應答,並且指定自己的序列號爲y,同時把用戶端的序列號加1作爲確認號ask,表示伺服器端已經接收到用戶端的SYN報文,此時伺服器處於SYN_RCVD的狀態。
3、第三次握手: 用戶端收到伺服器端返回的SYN報文後,會發送一個ACK報文,將伺服器端的序列號+1作爲ask資訊,並且將序列號+1作爲新的序列號,表示已經收到了伺服器端的SYN報文,此時用戶端處於ESTABLISHED狀態。伺服器端接收到ACK報文後媽耶處於ESTABLISHED狀態。
弄清這個問題,我們需要先弄明白三次握手分別的含義以及目的,能不能通過兩次握手來實現相同的目的。
因此,需要三次握手才能 纔能確認雙方的接收和發送能力是否正常。
試想如果是用兩次握手,則會出現下面 下麪這種情況:
如用戶端發出連線請求,但因連線請求報文丟失而未收到確認,於是用戶端再重傳一次連線請求。後來收到了確認,建立了連線。數據傳輸完畢後,就釋放了連線,用戶端共發出了兩個連線請求報文段,其中第一個丟失,第二個到達了伺服器端,但是第一個丟失的報文段只是在某些網路結點長時間滯留了,延誤到連線釋放以後的某個時間纔到達伺服器端,此時伺服器端誤認爲用戶端又發出一次新的連線請求,於是就向用戶端發出確認報文段,同意建立連線,不採用三次握手,只要伺服器端發出確認,就建立新的連線了,此時用戶端忽略伺服器端發來的確認,也不發送數據,則伺服器端一致等待用戶端發送數據,浪費資源。
伺服器第一次收到用戶端的 SYN 之後,就會處於 SYN_RCVD 狀態,此時雙方還沒有完全建立起連線,伺服器會把此種狀態下請求連線放在一個佇列裡,我們把這種佇列稱之爲半連線佇列。
當然還有一個全連線佇列,就是已經完成三次握手,建立起連線的就會放在全連線佇列中。如果佇列滿了就有可能會出現丟包現象。
**SYN-ACK 重傳次數:**伺服器發送完SYN-ACK包,如果未收到客戶確認包,伺服器進行首次重傳,等待一段時間仍未收到客戶確認包,進行第二次重傳。如果重傳次數超過系統規定的最大重傳次數,系統將該連線資訊從半連線佇列中刪除。
注意,每次重傳等待的時間不一定相同,一般會是指數增長,例如間隔時間爲 1s,2s,4s,8s…
當一端爲建立連線而發送它的SYN時,它爲連線選擇一個初始序號。ISN隨時間而變化,因此每個連線都將具有不同的ISN。ISN可以看作是一個32位元的計數器,每4ms加1 。這樣選擇序號的目的在於防止在網路中被延遲的分組在以後又被傳送,而導致某個連線的一方對它做錯誤的解釋。
三次握手的其中一個重要功能是用戶端和伺服器端交換 ISN(Initial Sequence Number),以便讓對方知道接下來接收數據的時候如何按序列號組裝數據。如果 ISN 是固定的,攻擊者很容易猜出後續的確認號,因此 ISN 是動態生成的。
其實第三次握手的時候,是可以攜帶數據的。但是,第一次、第二次握手不可以攜帶數據。
爲什麼這樣呢?大家可以想一個問題,假如第一次握手可以攜帶數據的話,如果有人要惡意攻擊伺服器,那他每次都在第一次握手中的 SYN 報文中放入大量的數據。因爲攻擊者根本就不理伺服器的接收、發送能力是否正常,然後瘋狂着重複發 SYN 報文的話,這會讓伺服器花費很多時間、記憶體空間來接收這些報文。
也就是說,第一次握手不可以放數據,其中一個簡單的原因就是會讓伺服器更加容易受到攻擊了。而對於第三次的話,此時用戶端已經處於 ESTABLISHED 狀態。對於用戶端來說,他已經建立起連線了,並且也已經知道伺服器的接收、發送能力是正常的了,所以能攜帶數據也沒啥毛病。
伺服器端的資源分配是在二次握手時分配的,而用戶端的資源分配是在完成三次握手時分配的,所以伺服器端容易受到SYN洪泛攻擊。SYN攻擊就是Client在短時間內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server則回覆 回復確認包,並等待Client確認,由於源地址不存在,因此Server需要不斷重發直至超時,這些僞造的SYN包將長時間佔用未連線佇列,導致正常的SYN請求因爲佇列滿而被丟棄,從而引起網路擁塞甚至系統癱瘓。SYN 攻擊是一種典型的 DoS/DDoS 攻擊。
檢測 SYN 攻擊非常的方便,當你在伺服器上看到大量的半連線狀態時,特別是源IP地址是隨機的,基本上可以斷定這是一次SYN攻擊。在 Linux/Unix 上可以使用系統自帶的 netstat 命令來檢測 SYN 攻擊。netstat -n -p TCP | grep SYN_RECV
建立一個連線需要三次握手,而終止一個連線要經過四次揮手(也有將四次揮手叫做四次握手的)。這由TCP的半關閉(half-close)造成的。所謂的半關閉,其實就是TCP提供了連線的一端在結束它的發送後還能接收來自另一端數據的能力。
TCP 連線的拆除需要發送四個包,因此稱爲四次揮手(Four-way handshake),用戶端或伺服器端均可主動發起揮手動作。
剛開始雙方都處於ESTABLISHED 狀態,假如是用戶端先發起關閉請求。四次揮手的過程如下:
1、第一次揮手: 用戶端發送一個FIN報文,報文中會指定一個序列號u,此時用戶端處於FIN_WAIT1狀態。即發出連線釋放報文(FIN=1,seq = u),並停止再發送數據,主動關閉TCP連線,進入FIN_WAIT1(終止等待1)狀態,等待伺服器端的確認。
2、第二次揮手: 伺服器端接收到FIN報文後,會發送ACK報文,且將用戶端的序列號+1作爲ack的值,以及自己的序列號v發送給用戶端,表示自己已經接收到用戶端的報文了,此時伺服器端處於CLOSE_WAIT狀態。此時TCP處於半關閉狀態,用戶端到伺服器端的連線釋放。用戶端在收到伺服器端的確認後,進入FIN_WAIT2狀態,等待伺服器端發出的連線釋放報文段。
3、第三次揮手: 如果伺服器端也想斷開連線,和用戶端的第一揮手一樣,發送FIN報文,且指定一個序列號,此時伺服器端處於LAST_ACK狀態。即伺服器端沒有要向用戶端發出的數據,伺服器端發出連線釋放報文段。
4、第四次揮手: 用戶端收到 FIN 之後,一樣發送一個 ACK 報文作爲應答,且把伺服器端的序列號值 +1 作爲自己 ACK 報文的序列號值,此時用戶端處於 TIME_WAIT 狀態。需要過一陣子以確保伺服器端收到自己的 ACK 報文之後纔會進入 CLOSED 狀態,伺服器端收到 ACK 報文之後,就處於關閉連線了,處於 CLOSED 狀態。此時TCP未釋放掉,需要經過時間等待計時器設定的時間2MSL後,用戶端才進入CLOSED狀態。
因爲當伺服器端收到用戶端的SYN連線請求報文後,可以直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連線時,當伺服器端收到FIN報文時,很可能並不會立即關閉SOCKET,所以只能先回覆 回復一個ACK報文,告訴用戶端,「你發的FIN報文我收到了」。只有等到我伺服器端所有的報文都發送完了,我才能 纔能發送FIN報文,因此不能一起發送。故需要四次揮手。
TIME_WAIT狀態也稱爲2MSL等待狀態。每一個具體TCP實現必須選擇一個報文段最大生存時間MSL(Maximum Segment LifeTime),它是任何報文被丟棄前在網路中的最長時間。這個時間是有限的,因此TCP報文段以IP數據報在網路內傳輸,而IP數據報則有限制其生存時間的TTL欄位。
爲了保證用戶端發送的最後一個ACK報文段能夠到達伺服器。因爲這個ACK有可能丟失,從而導致處在LAST-ACK狀態的伺服器收不到對FIN-ACK的確認報文。伺服器會超時重傳這個FIN-ACK,接着用戶端再重傳一次確認,重新啓動時間等待計時器。最後用戶端和伺服器都能正常的關閉。假設用戶端不等待2MSL,而是在發送完ACK之後直接釋放關閉,一但這個ACK丟失的話,伺服器就無法正常的進入關閉連線狀態。
兩個理由:
1、保證用戶端發送的最後一個ACK報文段能夠到達伺服器端。
這個ACK報文段有可能丟失,使得處於LAST_ACK狀態的伺服器端收不到對已發送的FIN+ACK報文段的確認,伺服器端超時重傳FIN+ACK報文段,而用戶端能在2MSL時間內收到這個重傳的FIN+ACK報文段,接着用戶端重傳一次確認,重新啓動2MSL計時器,最後用戶端和伺服器端都進入到CLOSED狀態,若用戶端在TIME-WAIT狀態不等待一段時間,而是發送完ACK報文段後立即釋放連線,則無法收到伺服器端重傳的FIN+ACK報文段,所以不會再發送一次確認報文段,則伺服器端無法正常進入到CLOSED狀態。
2、防止「已失效的連線請求報文段」出現在本連線中
用戶端在發送完最後一個ACK報文段後,再經過2MSL,就可以使本連線持續的時間內所產生的所有報文段都從網路中消失,使下一個新的連線中不會出現這種舊的連線請求報文段。
CLOSE_WAIT: CLOSE_WAIT是被動關閉連線是形成的。根據TCP狀態機,伺服器端收到用戶端發送的FIN,則按照TCP實現發送ACK,因此進入CLOSE_WAIT狀態。但如果伺服器端不執行close(),就不能由CLOSE_WAIT遷移到LAST_ACK,則系統中會存在很多CLOSE_WAIT狀態的連線。此時,可能是系統忙於處理讀、寫操作,而未將已收到FIN的連線,進行close。此時,recv/read已收到FIN的連線socket,會返回0。
TIME_WAIT: 用戶端接收到伺服器端的FIN報文以及對伺服器端發送ACK報文後,所處的狀態,需要等待2MSL時間才能 纔能轉換成CLOSED狀態。
Http響應碼:
域名解析 --》發起TCP的三次握手 --》建立TCP連線後發起http請求 --》伺服器響應http請求,瀏覽器得到html程式碼 --》瀏覽器解析html程式碼,並請求html程式碼中的資源(如js、css、圖片等)–》瀏覽器對頁面進行渲染呈現給使用者。
TCP協定保證數據傳輸可靠性的方式主要有:
計算方式: 在數據傳輸的過程中,將發送的數據段都當做一個16位元的整數。將這些整數加起來。並且前面的進位不能丟棄,補在後面,最後取反,得到校驗和。
**發送方:**在發送數據之前計算檢驗和,並進行校驗和的填充。
**接收方:**收到數據後,對數據以同樣的方式進行計算,求出校驗和,與發送方的進行比對。
注意:如果接收方比對校驗和與發送方不一致,那麼數據一定傳輸有誤。但是如果接收方比對校驗和與發送方一致,數據不一定傳輸成功。
序列號: TCP傳輸時將每個位元組的數據都進行了編號,這就是序列號。
確認應答: TCP傳輸的過程中,每次接收方收到數據後,都會對傳輸方進行確認應答。也就是發送ACK報文。這個ACK報文當中帶有對應的確認序列號,告訴發送方,接收到了哪些數據,下一次的數據從哪裏發。
序列號的作用不僅僅是應答的作用,有了序列號能夠將接收到的數據根據序列號排序,並且去掉重複序列號的數據。這也是TCP傳輸可靠性的保證之一。
在進行TCP傳輸時,由於確認應答與序列號機制 機製,也就是說發送方發送一部分數據後,都會等待接收方發送的ACK報文,並解析ACK報文,判斷數據是否傳輸成功。如果發送方發送完數據後,遲遲沒有等到接收方的ACK報文,這該怎麼辦呢?而沒有收到ACK報文的原因可能是什麼呢?
首先,發送方沒有接收到響應的ACK報文原因可能有兩點:
1、數據在傳輸過程中由於網路原因導致直接全體退包,接收方根本接收不到。
2、接收方接收到了響應數據,但是發送的ACK報文響應卻因爲網路原因丟包了。
TCP在解決這個問題的時候引入了超時重傳機制 機製,簡單理解就是發送方在發送完數據後等待一個時間,時間到達沒有接收到ACK報文,那麼對剛纔發送的數據進行重新發送。如果是剛纔第一個原因,接收方收到二次重發的數據後,便進行ACK應答。如果是第二個原因,接收方發現接收的數據已存在(判斷存在的根據就是序列號,所以上面說序列號還有去除重複數據的作用),那麼直接丟棄,仍舊發送ACK應答。
在Linux中(BSD Unix和Windows下也是這樣)超時以500ms爲一個單位進行控制,每次判定超時重發的超時時間都是500ms的整數倍。重發一次後,仍未響應,那麼等待2500ms的時間後,再次重傳。等待4500ms的時間繼續重傳。以一個指數的形式增長。累計到一定的重傳次數,TCP就認爲網路或者對端出現異常,強制關閉連線。
連線管理就是三次握手和四次揮手,保證可靠的連線,是保證可靠傳輸的前提。
接收端在接收到數據後,對其進行處理。如果發送端的發送速度太快,導致接收端的結束緩衝區很快的填充滿了。此時如果發送端仍舊發送數據,那麼接下來發送的數據都會丟包,繼而導致丟包的一系列連鎖反應,超時重傳呀什麼的。而TCP根據接收端對數據的處理能力,決定發送端的發送速度,這個機制 機製就是流量控制。
在TCP協定的報頭資訊當中,有一個16位元欄位的視窗大小。在介紹這個視窗大小時我們知道,視窗大小的內容實際上是接收端接收數據緩衝區的剩餘大小。這個數位越大,證明接收端接收緩衝區的剩餘空間越大,網路的吞吐量越大。接收端會在確認應答發送ACK報文時,將自己的即時視窗大小填入,並跟隨ACK報文一起發送過去。而發送方根據ACK報文裡的視窗大小的值的改變進而改變自己的發送速度。如果接收到視窗大小的值爲0,那麼發送方將停止發送數據。並定期的向接收端發送視窗探測數據段,讓接收端把視窗大小告訴發送端。
注:16位元的視窗大小最大能表示65535個位元組(64K),但是TCP的視窗大小最大並不是64K。在TCP首部中40個位元組的選項中還包含了一個視窗擴大因子M,實際的視窗大小就是16位元視窗欄位的值左移M位。每移一位,擴大兩倍。
TCP傳輸的過程中,發送端開始發送數據的時候,如果剛開始就發送大量的數據,那麼就可能造成一些問題。網路可能在開始的時候就很擁堵,如果給網路中在扔出大量數據,那麼這個擁堵就會加劇。擁堵的加劇就會產生大量的丟包,就對大量的超時重傳,嚴重影響傳輸。
所以TCP引入了慢啓動的機制 機製,在開始發送數據時,先發送少量的數據探路。探清當前的網路狀態如何,再決定多大的速度進行傳輸。這時候就引入一個叫做擁塞視窗的概念。發送剛開始定義擁塞視窗爲 1,每次收到ACK應答,擁塞視窗加 1。在發送數據之前,首先將擁塞視窗與接收端反饋的視窗大小比對,取較小的值作爲實際發送的視窗。
擁塞視窗的增長是指數級別的。慢啓動的機制 機製只是說明在開始的時候發送的少,發送的慢,但是增長的速度是非常快的。爲了控制擁塞視窗的增長,不能使擁塞視窗單純的加倍,設定一個擁塞視窗的閾值,當擁塞視窗大小超過閾值時,不能再按照指數來增長,而是線性的增長。在慢啓動開始的時候,慢啓動的閾值等於視窗的最大值,一旦造成網路擁塞,發生超時重傳時,慢啓動的閾值會爲原來的一半(這裏的原來指的是發生網路擁塞時擁塞視窗的大小),同時擁塞視窗重置爲 1。
擁塞控制是TCP在傳輸時儘可能快的將數據傳輸,並且避免擁塞造成的一系列問題。是可靠性的保證,同時也是維護了傳輸的高效性。
基於TCP/IP的四層協定的資訊封裝如下所示:
TCP報文頭部如下:
或者更詳細點:
**16位元埠號:**標示該段報文來自哪裏(源埠)以及要傳給哪個上層協定或應用程式(目的埠)。進行tcp通訊時,一般client是通過系統自動選擇的臨時埠號,而伺服器一般是使用知名伺服器端口號或者自己指定的埠號。
**32位元序列號:**表示一次tcp通訊過程(從建立連線到斷開)過程中某一次傳輸方向上的位元組流的每個位元組的編號。假定主機A和B進行tcp通訊,A傳送給B一個tcp報文段中,序號值被系統初始化爲某一個隨機值ISN,那麼在該傳輸方向上(從A到B),後續的所有tcp報文斷中的序號值都會被設定爲ISN加上該報文段所攜帶數據的第一個位元組在整個位元組流中的偏移。例如某個TCP報文段傳送的數據是位元組流中的第1025~2048位元組,那麼該報文段的序號值就是ISN+1025。
**32位元確認號:**用作對另一方發送的tcp報文段的響應。其值是收到對方的tcp報文段的序號值+1。假定主機A和B進行tcp通訊,那麼A發出的tcp報文段不但帶有自己的序號,也包含了對B發送來的tcp報文段的確認號。反之也一樣。
4位元頭部長度:表示tcp頭部有多少個32bit字(4位元組),因爲4位元最大值是15,所以最多有15個32bit,也就是60個位元組是最大的tcp頭部長度。
6位標誌位:
URG:緊急指針是否有效
ACK:表示確認好是否有效,攜帶ack標誌的報文段也稱確認報文段
PSH:提示接收端應用程式應該立即從tcp接受緩衝區中讀走數據,爲後續接收的數據讓出空間
RST:表示要求對方重建連線。帶RST標誌的tcp報文段也叫復位報文段
SYN:表示建立一個連線,攜帶SYN的tcp報文段爲同步報文段
FIN標誌:表示告知對方本端要關閉連線了。
16位元視窗大小:是TCP流量控制的一個手段,這裏說的視窗是指接收通告視窗,它告訴對方本端的tcp接收緩衝區還能容納多少位元組的數據,這樣對方就可以控制發送數據的速度。
16位元校驗和: 由發送端填充,接收端對tcp報文段執行CRC演算法以檢驗TCP報文段在傳輸過程中是否損壞。注意這個校驗不僅包括tcp頭部,也包括數據部分。這也是tcp可靠傳輸的一個重要保障。
16位元緊急指針: 是一個正的偏移量。它和序號欄位的值相加表示最後一個緊急數據的下一位元組的序號。因此這個欄位是緊急指針相對當前序號的偏移量。不妨稱之爲緊急便宜,發送緊急數據時會用到這個。
**TCP頭部選項:**最後一個選項欄位是可變長的可選資訊,最多包含40位元組的數據。典型的tcp頭部選項結構:
kind表示選項的型別,length表示選項的長度(全部),info表示選項的具體內容,常見的頭部選項有以下7種:
https://blog.csdn.net/cbjcry/article/details/84719662
https://www.cnblogs.com/redirect/p/10066702.html#1-%E8%AF%B7%E6%B1%82%E6%8A%A5%E6%96%87
https://mp.weixin.qq.com/s?__biz=MzI3ODcxMzQzMw==&mid=2247486310&idx=1&sn=3e5e02e7dd857d92e8cc2bc703133555&chksm=eb538e50dc24074613d5fedca4467a16cc0e0b35bfb90f9bc1717f8bb0c4d330c7ae961b36fa&scene=21#wechat_redirect
無狀態是指協定對於事務處理沒有記憶能力,伺服器不知道用戶端是什麼狀態。即我們給伺服器發送 HTTP 請求之後,伺服器根據請求,會給我們發送數據過來,但是,發送完,不會記錄任何資訊。
HTTP 是一個無狀態協定,這意味着每個請求都是獨立的,Keep-Alive 沒能改變這個結果。
缺少狀態意味着如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連線傳送的數據量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。
HTTP 協定這種特性有優點也有缺點,優點在於解放了伺服器,每一次請求「點到爲止」不會造成不必要連線佔用,缺點在於每次請求會傳輸大量重複的內容資訊。
用戶端與伺服器進行動態互動的 Web 應用程式出現之後,HTTP 無狀態的特性嚴重阻礙了這些應用程式的實現,畢竟互動是需要承前啓後的,簡單的購物車程式也要知道使用者到底在之前選擇了什麼商品。於是,兩種用於保持 HTTP 連線狀態的技術就應運而生了,一個是 Cookie,而另一個則是 Session。
Cookie 是用戶端的儲存空間,由瀏覽器來維持。具體來說 cookie 機制 機製採用的是在用戶端保持狀態的方案。
Cookie 的實現過程:
Cookie 會根據從伺服器端發送的響應報文內的一個叫做 Set-Cookie 的首部欄位資訊,通知用戶端儲存 Cookie,當下次用戶端再往該伺服器發送請求時,用戶端會自動在請求報文中加入 Cookie 值後發送出去。
也就是 Cookie 是伺服器生成的,但是發送給用戶端,並且由用戶端來儲存。每次請求加上 Cookie就行了。伺服器端發現用戶端發送過來的 Cookie 後,會去檢查究竟是從哪一個用戶端發來的連線請求,然後對比伺服器上的記錄,最後得到之前的狀態資訊。
與 Cookie 相對的一個解決方案是 Session,它是通過伺服器來保持狀態的。
當用戶端存取伺服器時,伺服器根據需求設定 Session,將對談資訊儲存在伺服器上,同時將標示 Session 的 SessionId 傳遞給用戶端瀏覽器,瀏覽器將這個 SessionId 儲存在記憶體中,我們稱之爲無過期時間的 Cookie。瀏覽器關閉後,這個 Cookie 就會被清掉,它不會存在於使用者的 Cookie 臨時檔案。
以後瀏覽器每次請求都會額外加上這個參數值,伺服器會根據這個 SessionId,就能取得用戶端的數據資訊。
如果用戶端瀏覽器意外關閉,伺服器儲存的 Session 數據不是立即釋放,此時數據還會存在,只要我們知道那個 SessionId,就可以繼續通過請求獲得此 Session 的資訊,因爲此時後台的 Session 還存在,當然我們可以設定一個 Session 超時時間,一旦超過規定時間沒有用戶端請求時,伺服器就會清除對應 SessionId 的 Session 資訊。
GET請求:
1、請求參數附在URL後
2、GET請求可被快取
3、GET請求保留在瀏覽器的歷史記錄中。
4、GET請求不應在處理敏感數據的時候使用。
5、GET請求有長度限制
6、GET請求應當只用於獲取數據。
POST請求:
1、請求參數附在請求體中。
2、POST不會被快取
3、POST 請求不會保留在瀏覽器歷史記錄中
4、POST 請求對數據長度沒有要求
Http請求數據包:請求行 + 請求頭 + 數據體
(1)請求行
包含三個內容 method + request-URI + http-version。
method 包含有 post , get, head,delete, put, connect, options, patch, propfind, propatch, mkcol, copy, move, lock, unlock, trace, head。
request-URI :請求地址
http-version:http協定版本
(2)請求頭
Accept:指瀏覽器或其他客戶可以接愛的MIME檔案格式。Servlet可以根據它判斷並返回適當的檔案格式。
User-Agent:是客戶瀏覽器名稱。
Host:對應網址URL中的Web名稱和埠號。
Accept-Langeuage:指出瀏覽器可以接受的語言種類,如en或en-us,指英語。
connection:用來告訴伺服器是否可以維持固定的HTTP連線。http是無連線的,HTTP/1.1使用Keep-Alive爲預設值,這樣,當瀏覽器需要多個檔案時(比如一個HTML檔案和相關的圖形檔案),不需要每次都建立連線
Cookie:瀏覽器用這個屬性向伺服器發送Cookie。Cookie是在瀏覽器中寄存的小型數據體,它可以記載和伺服器相關的使用者資訊,也可以用來實現對談功能。
Referer:表明產生請求的網頁URL。如比從網頁/icconcept/index.jsp中點選一個鏈接到網頁/icwork/search,在向伺服器發送的GET/icwork/search中的請求中,Referer是http://hostname:8080/icconcept/index.jsp。這個屬性可以用來跟蹤Web請求是從什麼網站來的。
User-Agent:是客戶瀏覽器名稱。
Content-Type:用來表名request的內容型別。可以用HttpServletRequest的getContentType()方法取得。
Accept-Charset:指出瀏覽器可以接受的字元編碼。英文瀏覽器的預設值是ISO-8859-1.
Accept-Encoding:指出瀏覽器可以接受的編碼方式。編碼方式不同於檔案格式,它是爲了壓縮檔案並加速檔案傳遞速度。瀏覽器在接收到Web響應之後先解碼,然後再檢查檔案格式。
(3)數據體
http響應數據包:狀態行 + 響應頭 + 響應正文
1、get:用戶端向伺服器端發起請求,獲得資源。請求獲得URL處所在的資源。
2、post:向伺服器端提交新的請求欄位。請求URL的資源後新增新的數據。
3、head:請求獲取URL資源的響應報告,即獲得URL資源的頭部
4、patch:請求區域性修改URL所在資源的數據項
5、put:請求修改URL所在資源的數據元素。
6、delete:請求刪除url資源的數據
Http請求數據包:請求行 + 請求頭 + 數據體
(1)請求行
包含三個內容 method + request-URI + http-version。
method 包含有 post , get, head,delete, put, connect, options, patch, propfind, propatch, mkcol, copy, move, lock, unlock, trace, head。
request-URI :請求地址
http-version:http協定版本
(2)請求頭
Accept:指瀏覽器或其他客戶可以接愛的MIME檔案格式。Servlet可以根據它判斷並返回適當的檔案格式。
User-Agent:是客戶瀏覽器名稱。
Host:對應網址URL中的Web名稱和埠號。
Accept-Langeuage:指出瀏覽器可以接受的語言種類,如en或en-us,指英語。
connection:用來告訴伺服器是否可以維持固定的HTTP連線。http是無連線的,HTTP/1.1使用Keep-Alive爲預設值,這樣,當瀏覽器需要多個檔案時(比如一個HTML檔案和相關的圖形檔案),不需要每次都建立連線
Cookie:瀏覽器用這個屬性向伺服器發送Cookie。Cookie是在瀏覽器中寄存的小型數據體,它可以記載和伺服器相關的使用者資訊,也可以用來實現對談功能。
Referer:表明產生請求的網頁URL。如比從網頁/icconcept/index.jsp中點選一個鏈接到網頁/icwork/search,在向伺服器發送的GET/icwork/search中的請求中,Referer是http://hostname:8080/icconcept/index.jsp。這個屬性可以用來跟蹤Web請求是從什麼網站來的。
User-Agent:是客戶瀏覽器名稱。
Content-Type:用來表名request的內容型別。可以用HttpServletRequest的getContentType()方法取得。
Accept-Charset:指出瀏覽器可以接受的字元編碼。英文瀏覽器的預設值是ISO-8859-1.
Accept-Encoding:指出瀏覽器可以接受的編碼方式。編碼方式不同於檔案格式,它是爲了壓縮檔案並加速檔案傳遞速度。瀏覽器在接收到Web響應之後先解碼,然後再檢查檔案格式。
(3)數據體
在HTTP1.0和HTTP1.1協定中都有對長連線的支援。其中HTTP1.0需要在request中增加」Connection: keep-alive「 header才能 纔能夠支援,而HTTP1.1預設支援.
http1.0請求與伺服器端的互動過程:
1、用戶端發出帶有包含一個header:」Connection: keep-alive「的請求
2、伺服器端接收到這個請求後,根據http1.0和」Connection: keep-alive「判斷出這是一個長連線,就會在response的header中也增加」Connection: keep-alive「,同是不會關閉已建立的tcp連線.
3、用戶端收到伺服器端的response後,發現其中包含」Connection: keep-alive「,就認爲是一個長連線,不關閉這個連線。並用該連線再發送request.轉到a),點選這裏瞭解 http 1.0 vs 2.0 區別。
HTTP 協定中的內容都是明文傳輸,HTTPS 的目的是將這些內容加密,確保資訊傳輸安全。最後一個字母 S 指的是 SSL/TLS 協定,它位於 HTTP 協定與 TCP/IP 協定中間。
1、Cookies是一種能夠讓網站伺服器把少量數據儲存到用戶端的硬碟或記憶體,或是從用戶端的硬碟讀取數據的一種技術。Cookies是當你瀏覽某網站時,由Web伺服器置於你硬碟上的一個非常小的文字檔案,它可以記錄你的使用者ID、密碼、瀏覽過的網頁、停留的時間等資訊。session: 當使用者請求來自應用程式的 Web 頁時,如果該使用者還沒有對談,則 Web 伺服器將自動建立一個 Session 物件。當對談過期或被放棄後,伺服器將終止該對談。cookie機制 機製:採用的是在用戶端保持狀態的方案,而session機制 機製採用的是在伺服器端保持狀態的方案。同時我們看到由於伺服器端保持狀態的方案在用戶端也需要儲存一個標識,所以session機制 機製可能需要藉助cookie機制 機製來達到儲存標識的目的。
2、Session是伺服器用來跟蹤使用者的一種手段,每個Session都有一個唯一標識:session ID。當伺服器建立了Session時,給用戶端發送的響應報文包含了Set-cookie欄位,其中有一個名爲sid的鍵值對,這個鍵值Session ID。用戶端收到後就把Cookie儲存瀏覽器,並且之後發送的請求報表都包含SessionID。HTTP就是通過Session和Cookie這兩個發送一起合作來實現跟蹤使用者狀態,Session用於伺服器端,Cookie用於用戶端
本文借鑑以下文章:
HTTP1.0和HTTP1.1和HTTP2.0的區別
面試官,不要再問我三次握手和四次揮手
網路基礎:TCP協定-如何保證傳輸可靠性
理解TCP報文段的頭部結構