**網絡**
**79\. http 響應碼 301 和 302 代表的是什么?有什么區別?**
答:301,302?都是HTTP狀態的編碼,都代表著某個URL發生了轉移。
**區別:?**
* 301?redirect:?301?代表永久性轉移(Permanently?Moved)。
* 302?redirect:?302?代表暫時性轉移(Temporarily?Moved?)。?
**80\. forward 和 redirect 的區別?**
Forward和Redirect代表了兩種請求轉發方式:直接轉發和間接轉發。
**直接轉發方式(Forward)**,客戶端和瀏覽器只發出一次請求,Servlet、HTML、JSP或其它信息資源,由第二個信息資源響應該請求,在請求對象request中,保存的對象對于每個信息資源是共享的。
**間接轉發方式(Redirect)**實際是兩次HTTP請求,服務器端在響應第一次請求的時候,讓瀏覽器再向另外一個URL發出請求,從而達到轉發的目的。
**舉個通俗的例子:**
直接轉發就相當于:“A找B借錢,B說沒有,B去找C借,借到借不到都會把消息傳遞給A”;
間接轉發就相當于:"A找B借錢,B說沒有,讓A去找C借"。
**81\. 簡述 tcp 和 udp的區別?**
* TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接。
* TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重復,且按序到達;UDP盡最大努力交付,即不保證可靠交付。
* Tcp通過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還可以對次序亂掉的分包進行順序控制。
* UDP具有較好的實時性,工作效率比TCP高,適用于對高速傳輸和實時性有較高的通信或廣播通信。
* 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信。
* TCP對系統資源要求較多,UDP對系統資源要求較少。
**82\. tcp 為什么要三次握手,兩次不行嗎?為什么?**
為了實現可靠數據傳輸, TCP 協議的通信雙方, 都必須維護一個序列號, 以標識發送出去的數據包中, 哪些是已經被對方收到的。 三次握手的過程即是通信雙方相互告知序列號起始值, 并確認對方已經收到了序列號起始值的必經步驟。
如果只是兩次握手, 至多只有連接發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認。
**83\. 說一下 tcp 粘包是怎么產生的?**
**①. 發送方產生粘包**
采用TCP協議傳輸數據的客戶端與服務器經常是保持一個長連接的狀態(一次連接發一次數據不存在粘包),雙方在連接不斷開的情況下,可以一直傳輸數據;但當發送的數據包過于的小時,那么TCP協議默認的會啟用Nagle算法,將這些較小的數據包進行合并發送(緩沖區數據發送是一個堆壓的過程);這個合并過程就是在發送緩沖區中進行的,也就是說數據發送出來它已經是粘包的狀態了。

**②. 接收方產生粘包**
接收方采用TCP協議接收數據時的過程是這樣的:數據到底接收方,從網絡模型的下方傳遞至傳輸層,傳輸層的TCP協議處理是將其放置接收緩沖區,然后由應用層來主動獲取(C語言用recv、read等函數);這時會出現一個問題,就是我們在程序中調用的讀取數據函數不能及時的把緩沖區中的數據拿出來,而下一個數據又到來并有一部分放入的緩沖區末尾,等我們讀取數據時就是一個粘包。(放數據的速度 > 應用層拿數據速度)?

**84\. OSI 的七層模型都有哪些?**
1. ### 應用層:網絡服務與最終用戶的一個接口。
2. ### 表示層:數據的表示、安全、壓縮。
3. ### 會話層:建立、管理、終止會話。
4. ### 傳輸層:定義傳輸數據的協議端口號,以及流控和差錯校驗。
5. ### 網絡層:進行邏輯地址尋址,實現不同網絡之間的路徑選擇。
6. ### 數據鏈路層:建立邏輯連接、進行硬件地址尋址、差錯校驗等功能。
7. ### 物理層:建立、維護、斷開物理連接。
###
**85\. get 和 post 請求有哪些區別?**
* GET在瀏覽器回退時是無害的,而POST會再次提交請求。
* GET產生的URL地址可以被Bookmark,而POST不可以。
* GET請求會被瀏覽器主動cache,而POST不會,除非手動設置。
* GET請求只能進行url編碼,而POST支持多種編碼方式。
* GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留。
* GET請求在URL中傳送的參數是有長度限制的,而POST么有。
* 對參數的數據類型,GET只接受ASCII字符,而POST沒有限制。
* GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。
* GET參數通過URL傳遞,POST放在Request body中。
**86\. 如何實現跨域?**
### **方式一:圖片ping或script標簽跨域**
**圖片ping**常用于跟蹤用戶點擊頁面或動態廣告曝光次數。?
**script標簽**可以得到從其他來源數據,這也是JSONP依賴的根據。?
**方式二:JSONP跨域**
JSONP(JSON with Padding)是數據格式JSON的一種“使用模式”,可以讓網頁從別的網域要數據。根據 XmlHttpRequest 對象受到同源策略的影響,而利用 元素的這個開放策略,網頁可以得到從其他來源動態產生的JSON數據,而這種使用模式就是所謂的 JSONP。用JSONP抓到的數據并不是JSON,而是任意的JavaScript,用 JavaScript解釋器運行而不是用JSON解析器解析。所有,通過Chrome查看所有JSONP發送的Get請求都是js類型,而非XHR。?

缺點:
* 只能使用Get請求
* 不能注冊success、error等事件監聽函數,不能很容易的確定JSONP請求是否失敗
* JSONP是從其他域中加載代碼執行,容易受到跨站請求偽造的攻擊,其安全性無法確保
*
**方式三:CORS**
Cross-Origin Resource Sharing(CORS)跨域資源共享是一份瀏覽器技術的規范,提供了 Web 服務從不同域傳來沙盒腳本的方法,以避開瀏覽器的同源策略,確保安全的跨域數據傳輸。現代瀏覽器使用CORS在API容器如XMLHttpRequest來減少HTTP請求的風險來源。與 JSONP 不同,CORS 除了 GET 要求方法以外也支持其他的 HTTP 要求。服務器一般需要增加如下響應頭的一種或幾種:
~~~
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
~~~
跨域請求默認不會攜帶Cookie信息,如果需要攜帶,請配置下述參數:
~~~
"Access-Control-Allow-Credentials": true
// Ajax設置
"withCredentials": true
~~~
**方式四:window.name+iframe**
window.name通過在iframe(一般動態創建i)中加載跨域HTML文件來起作用。然后,HTML文件將傳遞給請求者的字符串內容賦值給window.name。然后,請求者可以檢索window.name值作為響應。
* iframe標簽的跨域能力;
* window.name屬性值在文檔刷新后依舊存在的能力(且最大允許2M左右)。
每個iframe都有包裹它的window,而這個window是top window的子窗口。contentWindow屬性返回元素的Window對象。你可以使用這個Window對象來訪問iframe的文檔及其內部DOM。
~~~
<!--
下述用端口
10000表示:domainA
10001表示:domainB
-->
<!-- localhost:10000 -->
<script>
var iframe = document.createElement('iframe');
iframe.style.display = 'none'; // 隱藏
var state = 0; // 防止頁面無限刷新
iframe.onload = function() {
if(state === 1) {
console.log(JSON.parse(iframe.contentWindow.name));
// 清除創建的iframe
iframe.contentWindow.document.write('');
iframe.contentWindow.close();
document.body.removeChild(iframe);
} else if(state === 0) {
state = 1;
// 加載完成,指向當前域,防止錯誤(proxy.html為空白頁面)
// 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新特性,可以用來向其他所有的 window 對象發送消息。需要注意的是我們必須要保證所有的腳本執行完才發送 MessageEvent,如果在函數執行的過程中調用了它,就會讓后面的函數超時無法執行。
下述代碼實現了跨域存儲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一下,會報錯:
> Blocked?a?frame?with?origin?“http://localhost:10001”?from?accessing?a?frame?with?origin?“http://localhost:10000“.?Protocols,?domains,?and?ports?must?match.
避免該錯誤,可以在Safari瀏覽器中勾選開發菜單==>停用跨域限制。或者只能使用服務器端轉存的方式實現,因為Safari瀏覽器默認只支持CORS跨域請求。
**方式六:修改document.domain跨子域**
前提條件:這兩個域名必須屬于同一個基礎域名!而且所用的協議,端口都要一致,否則無法利用document.domain進行跨域,所以只能跨子域
在根域范圍內,允許把domain屬性的值設置為它的上一級域。例如,在”aaa.xxx.com”域內,可以把domain設置為 “xxx.com” 但不能設置為 “xxx.org” 或者”com”。
> 現在存在兩個域名aaa.xxx.com和bbb.xxx.com。在aaa下嵌入bbb的頁面,由于其document.name不一致,無法在aaa下操作bbb的js。可以在aaa和bbb下通過js將document.name?=?'xxx.com';設置一致,來達到互相訪問的作用。
**方式七:WebSocket**
WebSocket protocol 是HTML5一種新的協議。它實現了瀏覽器與服務器全雙工通信,同時允許跨域通訊,是server push技術的一種很棒的實現。相關文章,請查看:WebSocket、WebSocket-SockJS
需要注意:WebSocket對象不支持DOM 2級事件偵聽器,必須使用DOM 0級語法分別定義各個事件。
**方式八:代理**
同源策略是針對瀏覽器端進行的限制,可以通過服務器端來解決該問題
DomainA客戶端(瀏覽器) ==> DomainA服務器 ==> DomainB服務器 ==> DomainA客戶端(瀏覽器)
**87.說一下 JSONP 實現原理?**
jsonp 即 json+padding,動態創建script標簽,利用script標簽的src屬性可以獲取任何域下的js腳本,通過這個特性(也可以說漏洞),服務器端不在返貨json格式,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
- 空白目錄
- Java 最常見的 208 道面試題:第一模塊答案
- Java 最常見的 208 道面試題:第二模塊答案
- Java 最常見的 208 道面試題:第三模塊答案
- Java 最常見的 208 道面試題:第四模塊和第五模塊答案
- Java 最常見的 208 道面試題:第六模塊答案
- Java 最常見的 208 道面試題:第七模塊答案
- Java 最常見的 208 道面試題:第八模塊答案
- Java 最常見的 208 道面試題:第九模塊和第十模塊答案
- Java 最常見的 208 道面試題:第十一模塊答案
- Java 最常見的 208 道面試題:第十二模塊答案
- Java 最常見的 208 道面試題:第十三模塊答案
- Java 最常見的 208 道面試題:第十四模塊答案
- Java 最常見的 208 道面試題:第十五模塊答案
- Java 最常見的 208 道面試題:第十六模塊答案
- ava 最常見的 208 道面試題:第十七模塊答案
- Java 最常見的 208 道面試題:第十八模塊答案
- Java 最常見的 208 道面試題:第十九模塊答案
- 關于暑假自學內容