79. http 響應(yīng)碼 301 和 302 代表的是什么髓废?有什么區(qū)別震缭?
答:301嘶窄,302 都是HTTP狀態(tài)的編碼,都代表著某個(gè)URL發(fā)生了轉(zhuǎn)移脊僚。
區(qū)別:
- 301 redirect: 301 代表永久性轉(zhuǎn)移(Permanently Moved)相叁。
- 302 redirect: 302 代表暫時(shí)性轉(zhuǎn)移(Temporarily Moved )。
80. forward 和 redirect 的區(qū)別?
Forward和Redirect代表了兩種請(qǐng)求轉(zhuǎn)發(fā)方式:直接轉(zhuǎn)發(fā)和間接轉(zhuǎn)發(fā)增淹。
- 直接轉(zhuǎn)發(fā)方式(Forward)椿访,客戶(hù)端和瀏覽器只發(fā)出一次請(qǐng)求,Servlet虑润、HTML成玫、JSP或其它信息資源,由第二個(gè)信息資源響應(yīng)該請(qǐng)求拳喻,在請(qǐng)求對(duì)象request中哭当,保存的對(duì)象對(duì)于每個(gè)信息資源是共享的。
- 間接轉(zhuǎn)發(fā)方式**(Redirect)實(shí)際是兩次HTTP請(qǐng)求舞蔽,服務(wù)器端在響應(yīng)第一次請(qǐng)求的時(shí)候荣病,讓瀏覽器再向另外一個(gè)URL發(fā)出請(qǐng)求码撰,從而達(dá)到轉(zhuǎn)發(fā)的目的渗柿。
舉個(gè)通俗的例子:
- 直接轉(zhuǎn)發(fā)就相當(dāng)于:“A找B借錢(qián),B說(shuō)沒(méi)有脖岛,B去找C借朵栖,借到借不到都會(huì)把消息傳遞給A”;
- 間接轉(zhuǎn)發(fā)就相當(dāng)于:“A找B借錢(qián)柴梆,B說(shuō)沒(méi)有陨溅,讓A去找C借”。
81. 簡(jiǎn)述 tcp 和 udp的區(qū)別绍在?
- TCP面向連接(如打電話要先撥號(hào)建立連接);UDP是無(wú)連接的门扇,即發(fā)送數(shù)據(jù)之前不需要建立連接。
- TCP提供可靠的服務(wù)偿渡。也就是說(shuō)臼寄,通過(guò)TCP連接傳送的數(shù)據(jù),無(wú)差錯(cuò)溜宽,不丟失吉拳,不重復(fù),且按序到達(dá);UDP盡最大努力交付适揉,即不保證可靠交付留攒。
- TCP通過(guò)校驗(yàn)和,重傳控制嫉嘀,序號(hào)標(biāo)識(shí)炼邀,滑動(dòng)窗口、確認(rèn)應(yīng)答實(shí)現(xiàn)可靠傳輸剪侮。如丟包時(shí)的重發(fā)控制拭宁,還可以對(duì)次序亂掉的分包進(jìn)行順序控制。
- UDP具有較好的實(shí)時(shí)性,工作效率比TCP高红淡,適用于對(duì)高速傳輸和實(shí)時(shí)性有較高的通信或廣播通信不狮。
- 每一條TCP連接只能是點(diǎn)到點(diǎn)的;UDP支持一對(duì)一,一對(duì)多在旱,多對(duì)一和多對(duì)多的交互通信摇零。
- TCP對(duì)系統(tǒng)資源要求較多,UDP對(duì)系統(tǒng)資源要求較少桶蝎。
82. tcp 為什么要三次握手驻仅,兩次不行嗎?為什么登渣?
為了實(shí)現(xiàn)可靠數(shù)據(jù)傳輸噪服, TCP 協(xié)議的通信雙方, 都必須維護(hù)一個(gè)序列號(hào)胜茧, 以標(biāo)識(shí)發(fā)送出去的數(shù)據(jù)包中粘优, 哪些是已經(jīng)被對(duì)方收到的。 三次握手的過(guò)程即是通信雙方相互告知序列號(hào)起始值呻顽, 并確認(rèn)對(duì)方已經(jīng)收到了序列號(hào)起始值的必經(jīng)步驟雹顺。
如果只是兩次握手, 至多只有連接發(fā)起方的起始序列號(hào)能被確認(rèn)廊遍, 另一方選擇的序列號(hào)則得不到確認(rèn)嬉愧。
83. 說(shuō)一下 tcp 粘包是怎么產(chǎn)生的?
①. 發(fā)送方產(chǎn)生粘包
采用TCP協(xié)議傳輸數(shù)據(jù)的客戶(hù)端與服務(wù)器經(jīng)常是保持一個(gè)長(zhǎng)連接的狀態(tài)(一次連接發(fā)一次數(shù)據(jù)不存在粘包)喉前,雙方在連接不斷開(kāi)的情況下没酣,可以一直傳輸數(shù)據(jù);但當(dāng)發(fā)送的數(shù)據(jù)包過(guò)于的小時(shí)卵迂,那么TCP協(xié)議默認(rèn)的會(huì)啟用Nagle算法裕便,將這些較小的數(shù)據(jù)包進(jìn)行合并發(fā)送(緩沖區(qū)數(shù)據(jù)發(fā)送是一個(gè)堆壓的過(guò)程);這個(gè)合并過(guò)程就是在發(fā)送緩沖區(qū)中進(jìn)行的狭握,也就是說(shuō)數(shù)據(jù)發(fā)送出來(lái)它已經(jīng)是粘包的狀態(tài)了闪金。
②. 接收方產(chǎn)生粘包
84. OSI 的七層模型都有哪些?
- 應(yīng)用層:網(wǎng)絡(luò)服務(wù)與最終用戶(hù)的一個(gè)接口犬性。
- 表示層:數(shù)據(jù)的表示瞻离、安全、壓縮乒裆。
- 會(huì)話層:建立套利、管理、終止會(huì)話鹤耍。
- 傳輸層:定義傳輸數(shù)據(jù)的協(xié)議端口號(hào)肉迫,以及流控和差錯(cuò)校驗(yàn)。
- 網(wǎng)絡(luò)層:進(jìn)行邏輯地址尋址稿黄,實(shí)現(xiàn)不同網(wǎng)絡(luò)之間的路徑選擇喊衫。
- 數(shù)據(jù)鏈路層:建立邏輯連接、進(jìn)行硬件地址尋址杆怕、差錯(cuò)校驗(yàn)等功能族购。
- 物理層:建立、維護(hù)财著、斷開(kāi)物理連接联四。
85. get 和 post 請(qǐng)求有哪些區(qū)別撑碴?
- GET在瀏覽器回退時(shí)是無(wú)害的撑教,而POST會(huì)再次提交請(qǐng)求。
- GET產(chǎn)生的URL地址可以被Bookmark醉拓,而POST不可以伟姐。
- GET請(qǐng)求會(huì)被瀏覽器主動(dòng)cache,而POST不會(huì)亿卤,除非手動(dòng)設(shè)置愤兵。
- GET請(qǐng)求只能進(jìn)行url編碼,而POST支持多種編碼方式排吴。
- GET請(qǐng)求參數(shù)會(huì)被完整保留在瀏覽器歷史記錄里秆乳,而POST中的參數(shù)不會(huì)被保留。
- GET請(qǐng)求在URL中傳送的參數(shù)是有長(zhǎng)度限制的钻哩,而POST么有屹堰。
- 參數(shù)的數(shù)據(jù)類(lèi)型,GET只接受ASCII字符街氢,而POST沒(méi)有限制扯键。
- GET比POST更不安全,因?yàn)閰?shù)直接暴露在URL上珊肃,所以不能用來(lái)傳遞敏感信息荣刑。
- GET參數(shù)通過(guò)URL傳遞馅笙,POST放在Request body中。
86. 如何實(shí)現(xiàn)跨域厉亏?
方式一:圖片ping或script標(biāo)簽跨域
- 圖片ping常用于跟蹤用戶(hù)點(diǎn)擊頁(yè)面或動(dòng)態(tài)廣告曝光次數(shù)董习。
- script標(biāo)簽可以得到從其他來(lái)源數(shù)據(jù),這也是JSONP依賴(lài)的根據(jù)爱只。
方式二:JSONP跨域
JSONP(JSON with Padding)是數(shù)據(jù)格式JSON的一種“使用模式”阱飘,可以讓網(wǎng)頁(yè)從別的網(wǎng)域要數(shù)據(jù)。根據(jù) XmlHttpRequest 對(duì)象受到同源策略的影響虱颗,而利用沥匈。
- 只能使用Get請(qǐng)求
- 不能注冊(cè)success、error等事件監(jiān)聽(tīng)函數(shù)忘渔,不能很容易的確定JSONP請(qǐng)求是否失敗
- JSONP是從其他域中加載代碼執(zhí)行高帖,容易受到跨站請(qǐng)求偽造的攻擊,其安全性無(wú)法確保
方式三:CORS
Cross-Origin Resource Sharing(CORS)跨域資源共享是一份瀏覽器技術(shù)的規(guī)范畦粮,提供了 Web 服務(wù)從不同域傳來(lái)沙盒腳本的方法散址,以避開(kāi)瀏覽器的同源策略,確保安全的跨域數(shù)據(jù)傳輸⌒猓現(xiàn)代瀏覽器使用CORS在API容器如XMLHttpRequest來(lái)減少HTTP請(qǐng)求的風(fēng)險(xiǎn)來(lái)源预麸。與 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求儒将。服務(wù)器一般需要增加如下響應(yīng)頭的一種或幾種:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
跨域請(qǐng)求默認(rèn)不會(huì)攜帶Cookie信息吏祸,如果需要攜帶,請(qǐng)配置下述參數(shù):
"Access-Control-Allow-Credentials": true
// Ajax設(shè)置
"withCredentials": true
方式四:window.name+iframe
window.name通過(guò)在iframe(一般動(dòng)態(tài)創(chuàng)建i)中加載跨域HTML文件來(lái)起作用钩蚊。然后HTML文件將傳遞給請(qǐng)求者的字符串內(nèi)容賦值給window.name贡翘。然后,請(qǐng)求者可以檢索window.name值作為響應(yīng)砰逻。
- iframe標(biāo)簽的跨域能力鸣驱;
- window.name屬性值在文檔刷新后依舊存在的能力(且最大允許2M左右)。
每個(gè)iframe都有包裹它的window蝠咆,而這個(gè)window是top window的子窗口踊东。contentWindow屬性返回元素的Window對(duì)象。你可以使用這個(gè)Window對(duì)象來(lái)訪問(wèn)iframe的文檔及其內(nèi)部DOM刚操。
<!--
下述用端口
10000表示:domainA
10001表示:domainB
-->
<!-- localhost:10000 -->
<script>
var iframe = document.createElement('iframe');
iframe.style.display = 'none'; // 隱藏
var state = 0; // 防止頁(yè)面無(wú)限刷新
iframe.onload = function() {
if(state === 1) {
console.log(JSON.parse(iframe.contentWindow.name));
// 清除創(chuàng)建的iframe
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
} else if(state === 0) {
state = 1;
// 加載完成闸翅,指向當(dāng)前域,防止錯(cuò)誤(proxy.html為空白頁(yè)面)
// Blocked a frame with origin "http://localhost:10000" from accessing a cross-origin frame.
iframe.contentWindow.location = 'http://localhost:10000/proxy.html';
}
};
iframe.src = 'http://localhost:10001';
document.body.appendChild(iframe);
</script>
<!-- localhost:10001 -->
<!DOCTYPE html>
...
<script>
window.name = JSON.stringify({a: 1, b: 2});
</script>
</html>
方式五:window.postMessage()
HTML5新特性赡茸,可以用來(lái)向其他所有的 window 對(duì)象發(fā)送消息缎脾。需要注意的是我們必須要保證所有的腳本執(zhí)行完才發(fā)送 MessageEvent,如果在函數(shù)執(zhí)行的過(guò)程中調(diào)用了它占卧,就會(huì)讓后面的函數(shù)超時(shí)無(wú)法執(zhí)行遗菠。
下述代碼實(shí)現(xiàn)了跨域存儲(chǔ)localStorage
<!--
下述用端口
10000表示:domainA
10001表示:domainB
-->
<!-- localhost:10000 -->
<iframe src="http://localhost:10001/msg.html" name="myPostMessage" style="display:none;">
</iframe>
<script>
function main() {
LSsetItem('test', 'Test: ' + new Date());
LSgetItem('test', function(value) {
console.log('value: ' + value);
});
LSremoveItem('test');
}
var callbacks = {};
window.addEventListener('message', function(event) {
if (event.source === frames['myPostMessage']) {
console.log(event)
var data = /^#localStorage#(\d+)(null)?#([\S\s]*)/.exec(event.data);
if (data) {
if (callbacks[data[1]]) {
callbacks[data[1]](data[2] === 'null' ? null : data[3]);
}
delete callbacks[data[1]];
}
}
}, false);
var domain = '*';
// 增加
function LSsetItem(key, value) {
var obj = {
setItem: key,
value: value
};
frames['myPostMessage'].postMessage(JSON.stringify(obj), domain);
}
// 獲取
function LSgetItem(key, callback) {
var identifier = new Date().getTime();
var obj = {
identifier: identifier,
getItem: key
};
callbacks[identifier] = callback;
frames['myPostMessage'].postMessage(JSON.stringify(obj), domain);
}
// 刪除
function LSremoveItem(key) {
var obj = {
removeItem: key
};
frames['myPostMessage'].postMessage(JSON.stringify(obj), domain);
}
</script>
<!-- localhost:10001 -->
<script>
window.addEventListener('message', function(event) {
console.log('Receiver debugging', event);
if (event.origin == 'http://localhost:10000') {
var data = JSON.parse(event.data);
if ('setItem' in data) {
localStorage.setItem(data.setItem, data.value);
} else if ('getItem' in data) {
var gotItem = localStorage.getItem(data.getItem);
event.source.postMessage(
'#localStorage#' + data.identifier +
(gotItem === null ? 'null#' : '#' + gotItem),
event.origin
);
} else if ('removeItem' in data) {
localStorage.removeItem(data.removeItem);
}
}
}, false);
</script>
注意Safari一下联喘,會(huì)報(bào)錯(cuò):
Blocked a frame with origin “http://localhost:10001” from
accessing a frame with origin “http://localhost:10000“.
Protocols, domains, and ports must match.
避免該錯(cuò)誤,可以在Safari瀏覽器中勾選開(kāi)發(fā)菜單==>停用跨域限制辙纬』碓猓或者只能使用服務(wù)器端轉(zhuǎn)存的方式實(shí)現(xiàn),因?yàn)镾afari瀏覽器默認(rèn)只支持CORS跨域請(qǐng)求贺拣。
方式六:修改document.domain跨子域
前提條件:這兩個(gè)域名必須屬于同一個(gè)基礎(chǔ)域名!而且所用的協(xié)議蓖谢,端口都要一致,否則無(wú)法利用document.domain進(jìn)行跨域譬涡,所以只能跨子域
在根域范圍內(nèi)闪幽,允許把domain屬性的值設(shè)置為它的上一級(jí)域。例如涡匀,在”aaa.xxx.com”域內(nèi)盯腌,可以把domain設(shè)置為 “xxx.com” 但不能設(shè)置為 “xxx.org” 或者”com”。
現(xiàn)在存在兩個(gè)域名aaa.xxx.com和bbb.xxx.com陨瘩。在aaa下嵌入bbb的頁(yè)面腕够,由于其document.name不一致,無(wú)法在aaa下操作bbb的js舌劳≈阆妫可以在aaa和bbb下通過(guò)js將document.name = 'xxx.com';設(shè)置一致,來(lái)達(dá)到互相訪問(wèn)的作用甚淡。
方式七:WebSocket
WebSocket protocol 是HTML5一種新的協(xié)議大诸。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,同時(shí)允許跨域通訊材诽,是server push技術(shù)的一種很棒的實(shí)現(xiàn)底挫。相關(guān)文章,請(qǐng)查看:WebSocket脸侥、WebSocket-SockJS
需要注意:WebSocket對(duì)象不支持DOM 2級(jí)事件偵聽(tīng)器,必須使用DOM 0級(jí)語(yǔ)法分別定義各個(gè)事件盈厘。
方式八:代理**
同源策略是針對(duì)瀏覽器端進(jìn)行的限制睁枕,可以通過(guò)服務(wù)器端來(lái)解決該問(wèn)題
DomainA客戶(hù)端(瀏覽器) ==> DomainA服務(wù)器 ==> DomainB服務(wù)器 ==> DomainA客戶(hù)端(瀏覽器)
87.說(shuō)一下 JSONP 實(shí)現(xiàn)原理?
jsonp 即 json+padding沸手,動(dòng)態(tài)創(chuàng)建script標(biāo)簽外遇,利用script標(biāo)簽的src屬性可以獲取任何域下的js腳本,通過(guò)這個(gè)特性(也可以說(shuō)漏洞)契吉,服務(wù)器端不在返貨json格式跳仿,而是返回一段調(diào)用某個(gè)函數(shù)的js代碼,在src中進(jìn)行了調(diào)用捐晶,這樣實(shí)現(xiàn)了跨域菲语。