前端必須懂的計算機網絡知識—(跨域、代理、本地存儲)

前端必須懂的計算機網絡知識系列文章:

網絡模型數據處理過程

模型數據處理過程

域名的空間結構:

域名
因爲IP地址不方便記憶,因此一樣用具備層次和惟一性的域名和IP一一映射

DNS查找過程

  1. 客戶端向本地域名服務器發出請求,請求www.baidu.com的IP地址
  2. 本地DNS服務器向DNS根服務器發出請求,根DNS服務器會告訴本地服務器(.com)的服務器地址
  3. 本地DNS服務器會向(.com域)發請求,會獲得(baidu.com)的服務器地址
  4. 本地DNS服務器會向(baidu.com)發請求,會獲得(www.baidu.com)的IP地址61.135.169.125
  5. 本地DNS服務器向客戶端回覆域名(www.baidu.com)對應的IP地址是61.135.169.125

同源策略和跨域

瀏覽器只對網絡請求有同源限制,同源就是協議、域名和端口號一致,不一樣源的客戶端腳本在沒有明確受權的狀況下,不能讀寫對方XHR資源,反之不一樣源腳本讀取對方XHR資源就是跨域。以http://www.a.com/test/index.html 的同源檢測舉例:html

跨域的解決方案

  • jsonp:只支持GET,不支持POST請求,不安全XSS
  • postMessage:配合使用iframe,須要兼容IE六、七、八、9
  • document.domain:僅限於同一域名下的子域
  • cors:須要後臺配合進行相關的設置
  • websocket:須要後臺配合修改協議,不兼容,須要使用socket.io
  • proxy:使用代理去避開跨域請求,須要修改nginx、apache等的配置

jsonp

  • 瀏覽器對script標籤src屬性、link標籤ref屬性和img標籤src屬性沒有同源策略限制,利用這個「漏洞」就能夠很好的解決跨域請求,JSONP就是利用了script標籤無同源限制的特色來實現的。
  • 當向第三方站點請求時,咱們能夠將此請求放在script標籤的src屬性裏,這就如同請求一個普通的JS腳本,能夠自由的向不一樣的站點請求。
//建立script發送請求
//請求返回執行cb函數,而且刪除建立的script
//相似於$ajax中的jsonp
function jsonp(url,params,cb){
    return new Promimse((resolve,reject)=>{
        window[cb] = function(data){
            resolve(data);
            document.body.removeChild(script);
        }
        params={...params,cb},
        let arrs=[];
        for(let key in params){
            arrs.push(`${key}=${params[key]}`)
        }
        let script = document.createElement('script');
        script.src= url + '?'+ arrs.join('&');
        document.body.appendChild(script);
    })
}
jsonp({
    url:'https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su',
    params:{wd:%E8%B7%A8%E5%9F%9F},
    cb:'show'}).then(data=>{
        console.log(data)    
    })
複製代碼

jsonp

  1. 輸入https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=%E8%B7%A8%E5%9F%9F&&cb=show
  2. 返回show({q:"跨域",p:false,s:["跨域請求","跨域訪問","跨域問題","跨越速運單號查詢","跨域ajax","跨越物流","跨越","跨域速運","跨域請求解決方案","跨域問題怎麼解決"]});

postMessage

配合iframes使用,假設a.html位於服務localhost:3000,b.html位於服務器localhost:4000前端

//a.html
<body>
    <iframe id="frame"  src="http://localhost:4000/b.html" frameborder="0" onload="load()"></iframe>
    <script>
        function load(){
            let frame = document.getElementById('frame');
            frame.contentWindow.postMessage('我很帥','http://localhost:4000');
            window.onmessage =function (e){
                console.log(e.data);
            }
        }
    </script>
</body>
//otherWindow.postMessage(message, targetOrigin);
//otherWindow:指目標窗口,也就是給哪一個window發消息,是 window.frames 屬性的成員或者由 window.open 方法建立的窗口
//message:是要發送的消息,類型爲 String、Object (IE八、9 不支持)
//targetOrigin: 是限定消息接收範圍,不限制請使用'*'
//注意otherWindow和targetOrigin的區別
複製代碼
//b.html
<body>
    <script>
        //data:消息
        //origin:消息來源地址
        //source:源DOMWindow 對象
        window.onmessage =function (e){
            console.log(e.data);
            e.source.postMessage('不要臉',e.origin);
        }
    </script>
</body>
複製代碼

document.domain

//a.html
<body>
    helloa
    <iframe id="frame"  src="http://www.kongbz.com/b.html" frameborder="0" onload="load()"></iframe>
    <script>
        document.domain = 'kongbz.com';//設置domain
        function load(){
            let frame = document.getElementById('frame');
            console.log(frame.contentWindow.a)
        }
    </script>
</body>
複製代碼
<body>
    hellob
    <script>
        document.domain = 'kongbz.com';//設置domain
        var a = 'isB'
    </script>
</body>
複製代碼

websocket

客戶端發送信息給服務端,若是想實現客戶端向客戶端通訊,只能經過頁面->服務端->另外一個頁面nginx

//客戶端
<body>
    hellob
    <script>
        let socket = new WebSocket('ws://localhost:3000');
        socket.onopen = function(){
            socket.send('我很帥')
        }
        socket.onmessage = function(e){
            console.log(e.data)
        }
    </script>
</body>
複製代碼
//服務端
let express = require('express');
let Websocket = require('wss');
let wss= new WebSocket.Server({port:3000})
wss.on('connection',function(ws){
    ws.on('message',function(data){
        console.log(data);
        ws.send('不要臉');
    })
})
let app = new express();
app.listen(3000)
複製代碼

cors

const http = require('http')
const whitList = ['http://localhost:4000'];
http.createServer(function (req, res) {
  let origin = req.headers.origin;
  //在白名單中的域名才能訪問
  if(whitList.includes(origin)){
    //容許的域名(* 全部域),*不能和Access-Control-Allow-Credentials一塊兒使用
    res.header("Access-Control-Allow-Origin", "*");
    //容許攜帶哪一個頭訪問,不設置不能攜帶參數
    res.header("Access-Control-Allow-Headers","ContentType");
    //容許的方法,不設置默認支持GET、HEAD、POST,其餘類型必須設置才能處理請求
    res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    //運行攜帶cookie,設置以後還能服務器才能接受cookie
    res.header("Access-Control-Allow-Credentials",true);
    //容許前端獲取哪一個頭,不設置瀏覽器不能解析後臺返回的參數
    res.header("Access-Control-Allow-Expose-Headers",'ContentType');
    if(req.method=== 'OPTIONS'){
        res.end()
    }
  }
}).listen(9000, function () {
    console.log('server is runing at 9000')
})
複製代碼

proxy

例如test.a.cn/index.html頁面去調用test.b.cn/service.jsongit

//nginx.conf
location / {
    root;
    index index.html index.htm;
}
location ~.*\.json {
    root json;
    add_header "Access-Control-Allow-Origin" "*";
}
複製代碼

代理和網關

  • 代理是一種有轉發功能的應用程序,它扮演了位於服務器和客戶端'中間人'的角色,接收客戶端發送的請求不改變請求的URI並轉發給服務器,同時也接收服務器返回的相應並轉發客戶端
  • 緩存代理:代理轉發響應時會預先將資源緩存在代理服務器上當代理再次接收到對相同資源的請求時,就能夠不從源服務器那裏獲取資源,而是將以前緩存的資源做爲響應返回
  • 透明代理:轉發請求或響應時,不對報文作任何加工的代理類型
  • 網關是轉發其餘服務器通訊數據的服務器,接收從客戶端發送來的請求時,它就像本身擁有資源的源服務器同樣對請求進行處理,其工做機制和代理相似,而網關能使通訊線路上的服務器提供非HTTP協議的服務。

反向代理

  • 你們都有過這樣的經歷,撥打10086客服電話,可能一個地區的10086客服有幾個或者幾十個,你永遠都不須要關心在電話那頭的是哪個,叫什麼,男的,仍是女的,漂亮的仍是帥氣的,你都不關心,你關心的是你的問題能不能獲得專業的解答,你只須要撥通了10086的總機號碼,電話那頭總會有人會回答你,只是有時慢有時快而已。那麼這裏的10086總機號碼就是咱們說的反向代理。客戶不知道真正提供服務人的是誰。
  • 反向代理隱藏了真實的服務端,當咱們請求 www.baidu.com 的時候,就像撥打10086同樣,背後可能有成千上萬臺服務器爲咱們服務,但具體是哪一臺,你不知道,也不須要知道,你只須要知道反向代理服務器是誰就行了,www.baidu.com 就是咱們的反向代理服務器,反向代理服務器會幫咱們把請求轉發到真實的服務器那裏去。Nginx就是性能很是好的反向代理服務器,用來作負載均衡。

負載均衡和動靜分離

  • 負載均衡是反向代理的一種,後端多臺服務器,nginx根據權重、壓力、帶寬的分配服務器,避免等待和擁塞
  • 動靜分離是反向代理的一種,後端服務器分爲動態資源服務器和靜態資源服務器,nginx會根據請求分配服務器,區分處理邏輯,加快響應

cookie、localstroage、sessionstroage的區別

  • Cookie適合存儲一些session信息:
    1. cookie限制大小,約4k左右,不適合存儲業務數據,尤爲是數據量較大的值
    2. 存在有效期,到期自動銷燬
    3. cookie會每次隨http請求一塊兒發送,浪費寬
    4. cookie設置了domain能夠在子域共享跨域
    5. 可使用爬蟲抓取
  • localstroage適合存儲應用共享的地址信息等:
    1. 存儲數據量大,5M或者更大
    2. 有效期爲永久
    3. 不會隨http請求一塊兒發送
    4. 不能跨域,可是可使用postMessage和iframe消除這個影響,例如:cross-storage
    5. 在瀏覽器的隱私模式下不能讀取
    6. 不能被爬蟲讀取
  • sessionstroage適合存儲瀏覽狀態等:
    1. 存儲數據量大,5M或者更大
    2. 有效期爲到瀏覽器關閉
    3. 不會隨http請求一塊兒發送
    4. 不能被爬蟲讀取

結語

IT即互聯網技術,從事的工做和網絡有很大的關係,前端要負責和後臺(服務器)進行交互,其必然得通過網絡,因此懂點網絡知識有很大的幫助。接下來會介紹:github

  • TCP
  • HTTP
  • HTTPS
相關文章
相關標籤/搜索