HTTP協議原理

 

 

應用層:爲應用軟件提供了不少服務,構建於協議層,屏蔽網絡傳輸相關細節javascript

傳輸層:TCP、UPD協議,向用戶提供可靠的端到端的服務,傳輸層向高層屏蔽了下層數據通訊的細節css

物理層:定義物理設備如何傳輸數據的(電腦,網線,光纜)html

數據鏈路層:在通訊實體間創建數據鏈路鏈接(軟件服務,有了物理的鏈接,還須要軟件的鏈接,這兩邊能夠傳輸數據)java

網絡層:爲數據在結點之間傳輸建立邏輯鏈路(電腦訪問百度的服務器,那麼如何查到百度的地址,這就是網絡層的邏輯)node

HTTP1.1:算法

持久鏈接、pipeline,參考http://www.javashuo.com/article/p-uxpvhudn-dk.htmljson

增長host和其餘一些命令:host能夠在同一臺物理服務器上能夠跑不一樣的服務(node、java),就能夠經過host字段,指明,都是請求的是這臺物理服務器上的服務,可是具體是哪一個軟件服務node仍是Java,就是經過host來判斷的跨域

HTTP2.0:瀏覽器

全部數據以二進制傳輸,幀來傳輸(1.1是字符串),所以同一個鏈接裏面發送的多個請求再也不須要安裝順序來緩存

頭信息壓縮(1.1中發送和響應的過程當中,不少頭信息都是須要完整的發送和返回的,可是其實不少的字段用字符串保存,佔用帶寬比較大,頭壓縮能夠節約帶寬)以及推送(服務端主動發送信息的,好比:HTML中有不少的CSS、JS文件都是引用進來,咱們請求完HTML文件而後再根據文件裏面的鏈接去請求css、js文件,這是按順序的串行的,有了推送以後,發起HTML請求,再發送完HTML文件後,服務器會主動的將css 、js文件返回,而不須要你再發送請求,這就是並行的)等提升效率的功能

URI: 用來惟一標示互聯網上的信息資源,包括URL和URN

URL:統一資源定位器

URN:永久統一資源定位符,普通的狀況,要是資源移動了,就會返回404,可是URN狀況下,資源移動以後還能被找到,URN始終指向那個資源

method: get(獲取這個數據)、put(更新這個數據)、post(建立這個數據)、delete(刪除這個數據)

跨域:

請求是已經發送了,瀏覽器是會發送這個請求的,服務器也返回了,瀏覽器也接受了返回內容,只是瀏覽器發現,返回的內容沒有'Access-Control-Allow-Origin':'*'因此瀏覽器忽略返回的結果,這是瀏覽器提供的功能。

好比:有三個文件server.js,server2.js,test.html

//server.js
const http = require('http')
const fs = require('fs')

http.createServer(function (request, response){
    console.log('request come', request.url)

    const html = fs.readFileSync('test.html', 'utf8')
    response.writeHead(200, {
        'Content-Type': 'text/html'
    })
    response.end(html)
}).listen(8888)

console.log('server listening on 8888')

  

//server2.js
const http = require('http')

http.createServer(function (request, response){
    console.log('request come', request.url)
    response.writeHead(200, {
        'Access-Control-Allow-Origin': 'http://127.0.0.1:8888'//test.html//發起對server2的請求,經過在server2這個服務器上設置’Access-Control-Allow-Origin‘設置對應發起請求的地址容許請求的發起
    })
    response.end('123')
}).listen(8887)

console.log('server listening on 8887')

  

<!-- test.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    var xhr = new XMLHttpRequest()
    xhr.open('GET', 'http://127.0.0.1:8887/')
    xhr.send()
</script>
</html>

  CORS預請求:

跨域的時候,默認容許的方法只有:get,head,post,其餘的默認不容許,瀏覽器有一個預請求會去驗證的。也就是說這三個不須要預請求驗證,其餘的方法須要預請求驗證。

容許Content-Type:text/plain,multipart/form-data,application/x-www-form-urlencoded,這幾個不須要預請求,其餘的都須要。

預請求例子以下:

server.js不變

server2.js變成以下:

//server2.js
const http = require('http')

http.createServer(function (request, response){
    console.log('request come', request.url)
    response.writeHead(200, {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'X-Test-Cors',
        'Access-Control-Allow-Methods': 'POST,PUT,Delete',
        'Access-Control-Max-Age': '1000'
    })
    response.end('123')
}).listen(8887)

console.log('server listening on 8887')

test.html改爲以下:

<!-- test.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    fetch('http://localhost:8887',{
        method: 'PUT',   method: 'PUT',//原本默認狀況下,跨域只容許get,post,header請求,可是由於server2.js已經設置了'Access-Control-Allow-Methods': 'POST,PUT,Delete',所以不會報錯
        headers: {
            'X-Test-Cors': '123'//原本默認狀況下,跨域不容許自定義請求頭,可是由於server2.js已經設置了'Access-Control-Allow-Headers': 'X-Test-Cors',,所以不會報錯
        }
    })
</script>
</html>

  更加詳細的解釋參考:http://www.ruanyifeng.com/blog/2016/04/cors.html

Cache-Control可緩存性

public:HTTP通過的任何地方,任何代理均可以緩存

private:只有發起請求的瀏覽器能夠緩存

no-cache:你能夠在本地,proxy服務器緩存,每次都須要去源服務器驗證一下,若是服務器告訴你可使用本地的緩存,你纔可使用本地的緩存

no-store:完全的,本地,代理服務器都不能夠緩存,每次都須要去服務器拿資源。

no-transform:某些資源可能不少,某些服務器可能會去壓縮,no-transform 就是用來告訴代理服務器不要去壓縮等的transform

max-age:表明緩存的最長時間。若是cache-control中有max-age,同時又有Last-modified,那麼只有當max-age過時了,纔會經過Last-modified進行緩存協商,由於max-age就是服務端告訴客戶端的,因此max-age優先。

s-maxage:s-maxage是在代理服務器裏面的,若是max-age和s-maxage都設置了,那麼在代理服務器裏面會用s-maxage代理max-age,可是瀏覽器裏面仍是max-age

max-stale:就是說即便緩存已通過期了,可是隻要還在max-stale的時間段內,就會用發起請求一方的過時的緩存

must-revalidate:若是已通過期了,那麼必須再去源服務端去請求,獲取資源而後再沿驗證是否是真的過時了,而不能直接使用緩存

proxy-revalidate:用在緩存服務器中的,若是已通過去那麼必須再去源服務端去請求,獲取資源而後再沿驗證是否是真的過時了,而不能直接使用緩存

在瀏覽器中用到的有:public、private、no-cache,max-age,must-revalidate

若是設置了max-age,若是在max-age時間期間靜態資源發生了改變,可是這時候瀏覽器仍是會從緩存中讀取資源,而不會去請求最新的資源,這樣就矛盾了,如何解決尼?設置了max-age後,利用hash原理實現動態緩存靜態資源文件,根據打包好的靜態資源,計算出一個hash碼,當靜態資源變化了,hash碼就發生了變化。URL就發生變化了,這樣就會去請求新的資源。

若是是‘Cache-Control’:‘no-cache’,那麼每次請求資源,都須要去服務器問一問,驗證一下資源有沒有更新,那麼如何驗證?有兩種驗證方式:

第一種:經過Last-modified和if-modified-since,當第一次請求時,服務器會把last-modified發送給瀏覽器,當瀏覽器發起第二次請求時,瀏覽器會用if-modified-since帶上以前的last-modified,而後服務器驗證瀏覽器的request中的if-modified-since和服務器保持的last-modified是否一致,若是一致,那麼就不須要返回資源返回304(即便返回資源,瀏覽器也會從緩存中讀取數據,而不是使用返回的資源,由於瀏覽器會經過304這個有語義的狀態碼得知沒有改變,使用原來的緩存),若是不一致就返回新的資源,返回200狀態碼。

Last-modified有什麼缺點:

  • 某些服務端不能獲取精確的修改時間
  • 文件修改時間改了,可是文件內容卻沒有變

第二種,就是經過Etag和If-Match,和上面的道理是同樣的。

上面的驗證是基於‘Cache-Control’:‘no-cache’的,才這樣驗證,若是‘Cache-Control’:‘no-store’,那麼就是真正的不會緩存了

能夠參考:https://blog.csdn.net/lqlqlq007/article/details/79940017

 緩存流程:

 

HTTP長鏈接

瀏覽器的Connection-id是查看建立的TCP鏈接的ID

HTTP1.1 瀏覽器容許併發的建立TCP鏈接,Chrome能夠併發建立6個TCP鏈接,可是在一個TCP鏈接上只能一個接一個的發送請求,不能一次併發的發送多個請求

'Connection':'keep-alive'長鏈接,就是TCP鏈接不會關閉,會不斷的複用

HTTP2.0在一個域裏面用一個TCP 鏈接,這個TCP鏈接容許併發的發送請求

Cookie和Session

什麼是cookie?服務器返回的Set-Cookie(鍵值對)這個header字段,而後保持在瀏覽器中的一個內容。而後在下次同域請求數據時帶上這個cookie。鍵值對,能夠設置多個。服務器端發現客戶端發送過來的Cookie後,會去檢查到底是從哪個客戶端發送來的鏈接請求,而後對比服務器上的記錄,最後獲得以前的狀態信息

屬性:

max-age(你這個cookie的有效時間有多長),和expires(到什麼時間點過時)設置過時時間

Secure表示cookie只有在https請求的時候纔會發送

HttpOnly設置了以後,禁止用JavaScript訪問就沒法經過document.cookie進行訪問,能夠防止CSRF攻擊。

能夠用domain設置主域名下的全部二級域名都是能夠訪問的:

數據協商:

請求:

Accept:想要的數據類型

Accept-Encoding:數據的壓縮方式

Accept-Language:想要返回的數據的語言,中文、英文

User-Agent:聲明本身是什麼環境,PC仍是移動端,想要返回的是PC端的頁面仍是移動端的頁面

響應:

Content-Type:從Accept選擇一種數據格式返回,告訴說返回了什麼樣的數據格式,text/plain,text/html,image/jpeg,image/png,application/json,application/javascript,video/*,video/mp4,application/x-www-form-urlencoded(http://www.javashuo.com/article/p-wcuvzlrd-kc.html),multipart/form-data(表單提交多種數據類型,文件,圖片,字符串等)

 

Content-Encoding:deflate,gzip,br,compress(UNIX系統的標準壓縮),identity(不進行編碼)聲明返回的數據是以什麼方式壓縮的在瀏覽器裏面的Size包含兩個值,上面的值是整個返回的數據(header+body)被壓縮後傳輸過程當中的數據,下面的是body到了瀏覽器後解壓後的body數據。

Content-Language:聲明返回的語言

重定向:

當資源的路徑已經修改了,可是瀏覽器不知道,仍然按照原來的路徑訪問,這是後服務器端要進行重定向,告訴瀏覽器地址已經變了。302有語義(要跳轉)若是改爲200是不會跳轉的,經過Location進行直接跳轉,同一個域因此不須要host

301與302區別:

301是永久重定向,302是臨時性重定向,採用302的時候,用戶每次輸入原來的地址發起請求,都會有兩次請求,一次是原來的地址的請求,而後跳轉進行第二次請求,第二次是重定向地址的請求。301的時候第一次會有兩次請求,一次是原來的地址的請求,而後跳轉進行第二次請求,第二次是重定向地址的請求。可是當第二次用戶再輸入一樣的原來的地址的時候,只有一次請求,就是重定向地址的請求,由於瀏覽器會進行緩存,記住了這個重定向地址,每次用戶輸入原來的地址在瀏覽器上就進行了重定向,直接跳轉到緩存的地址上了,而不須要再發送到服務器上進行重定向。這個緩存還時間比較長,所以要用301的時候慎重,這是不能反悔的。

302和303區別:

 

307和302區別:

 

HTTPS 

公鑰(互聯網上全部人均可以拿到的),私鑰是在握手的時候進行傳輸

過程:

一、客戶端生成隨機數,發送給服務器,帶上支持的加密套件,由於服務器有不少加密的方法

二、服務端把客戶端的隨機數先存着,而後服務端也生成隨機數,發送給客戶端,帶上服務端證書(公鑰)

三、客戶端拿到服務端的隨機數也先存着,而後經過服務端證書(公鑰)生成預主祕鑰,生成過程當中也會有一個隨機數,隨機數被加密後傳輸給服務器這裏

四、服務器私鑰解密獲得預主祕鑰。

五、客戶端和服務端對這三個隨機數進行算法操做,生成主祕鑰。所以兩邊的主祕鑰是同樣的,能夠用來加密解密。

 

HTTP2

信道複用

分幀傳輸:每一幀,誰先到,誰後到沒有關係,等全部幀到了,會根據幀信息進行從新組合,所以能夠在一個TCP鏈接裏面併發的發送不一樣的請求

服務器推送

單臺虛擬機實現多個域名

Host:http://www.javashuo.com/article/p-nbyfnmhr-cp.html

 通訊數據轉發程序:代理、網關、隧道:

相關文章
相關標籤/搜索