国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

HTTP面試指南

FreeZinG / 1909人閱讀

摘要:報文主體并不是一定要有的。緩存緩存作用減少了冗余的數據傳輸,節省了網費。當資源發生改變時,也隨之發生變化。本人水平有限,有不足之處,望大家指出改正。

前言

或許你在面試時遇到過這樣的問題:從輸入URL到瀏覽器顯示頁面發生了什么?
簡單的回答就是:

DNS解析

TCP建立連接

發送HTTP請求

服務器處理請求

如果有緩存直接讀緩存

沒有緩存返回響應內容

TCP斷開連接

瀏覽器解析渲染頁面

如果你覺得這樣回答過于簡單,不如來深入了解一下吧。

網絡基礎

在此之前,先了解一下TCP/IP基礎知識。

TCP/IP參考模型

早期的TCP/IP模型是一個四層結構,從下往上依次是網絡接口層、互聯網層、傳輸層和應用層,后來將網絡接口層劃分為了物理層和數據鏈路層

應用層(Application)提供網絡與用戶應用軟件之間的接口服務

傳輸層(Transimission)提供建立、維護和取消傳輸連接功能,負責可靠地傳輸數據(PC)
傳輸層有兩個性質不同的協議:TCP(傳輸控制協議)和UDP(用戶數據報協議)

網絡層(Network)處理網絡間路由,確保數據及時傳送(路由器)

數據鏈路層(DataLink)負責無錯傳輸數據,確認幀、發錯重傳等(交換機)

物理層(Physics)提供機械、電氣、功能和過程特性(網卡、網線、雙絞線、同軸電纜、中繼器)

各層常用協議

這里可以看到HTTP協議是構建于TCP之上,屬于應用層協議

具體過程 1. DNS解析

DNS服務是和HTTP協議一樣位于應用層的協議,提供域名到IP地址的解析服務。

得到IP地址后就可以建立連接了,這里還有兩個知識需要了解:

持久連接

持久連接(也稱為HTTP keep-alive)的特點是,只要任意一段沒有提出斷開連接,就保持TCP連接狀態。

管線化

持久連接建立后就可以使用管線化發送了,可以同時并發多個請求,不用等待一個接一個的響應。(在這里我想到了流的pipe方法。)

2. TCP連接與斷開 2.1 TCP報文格式


大致說一下:

計算機通過端口號識別訪問哪個服務,比如http;源端口號進行隨機端口,目的端口決定哪個程序進行接收

數據序號和確認序號用于保障傳輸數據的完整性和順序

需要注意的是TCP的連接、傳輸和斷開都受六個控制位的指揮(比如三次握手和四次揮手)

PSH(push急迫位)緩存區將滿,立刻速度傳輸

RST(reset重置位)連接斷了重新連接

URG(urgent緊急位)緊急信號

ACK(acknowlegement確認)為1就表示確認號

SYN(synchronous建立聯機)同步序號位 TCP建立連接時將這個值設為1

用戶數據存儲了應用層生成的HTTP報文

了解了這些,那么開始講重點

2.2 TCP三次握手和四次揮手

三次握手

客戶端先發送一個帶SYN標志的數據包給服務器端

服務器收到后,回傳一個帶有SYN/ACK標志的數據包表示確認收到

客戶端再發送一個帶SYN/ACK標志的數據包,代表握手結束

四次揮手

客戶端向服務器發出了FIN報文段

服務器收到后,回復一個ACK應答

服務器也向客戶端發送一個FIN報文段,隨后關閉了服務器端的連接

客戶端收到之后,又向服務器回復一個ACK應答,過了一段計時等待,客戶端也關閉了連接(計時等待是為了確認服務器端已正常關閉)

四次揮手并不是必然的,當服務器已經沒有內容發給客戶端了,就直接發送FIN報文段,這樣就變成了三次揮手。
3. HTTP請求/響應 3.1 HTTP報文

HTTP報文大致可分為報文首部和報文主體兩塊,兩者由空行(就相當于用了兩個換行符rnrn)來劃分。報文主體并不是一定要有的。

3.1.1 請求報文

常用請求行方法:

GET 獲取資源

POST 向服務器端發送數據,傳輸實體主體

PUT 傳輸文件

HEAD 獲取報文首部

DELETE 刪除文件

OPTIONS 詢問支持的方法

TRACE 追蹤路徑

3.1.2 響應報文

說到響應報文,就必要談到狀態碼:

2XX 成功

200(OK) 客戶端發過來的數據被正常處理

204(Not Content) 正常響應,沒有實體

206(Partial Content) 范圍請求,返回部分數據,響應報文中由Content-Range指定實體內容

3XX 重定向

301(Moved Permanently) 永久重定向

302(Found) 臨時重定向,規范要求方法名不變,但是都會改變

303(See Other) 和302類似,但必須用GET方法

304(Not Modified) 狀態未改變 配合(If-Match、If-Modified-Since、If-None_Match、If-Range、If-Unmodified-Since) (通常緩存會返回304狀態碼)

4XX 客戶端錯誤

400(Bad Request) 請求報文語法錯誤

401 (unauthorized) 需要認證

403(Forbidden) 服務器拒絕訪問對應的資源

404(Not Found) 服務器上無法找到資源

5XX 服務器端錯誤

500(Internal Server Error) 服務器故障

503(Service Unavailable) 服務器處于超負載或正在停機維護

3.1.3 首部

通用首部

首部字段名 說明
Cache-Control 控制緩存行為
Connection 連接的管理
Date 報文日期
Pragma 報文指令
Trailer 報文尾部的首部
Trasfer-Encoding 指定報文主體的傳輸編碼方式
Upgrade 升級為其他協議
Via 代理服務器信息
Warning 錯誤通知

請求首部

首部字段名 說明
Accept 用戶代理可處理的媒體類型
Accept-Charset 優先的字符集
Accept-Encoding 優先的編碼
Accept-Langulage 優先的語言
Authorization Web認證信息
Expect 期待服務器的特定行為
From 用戶的電子郵箱地址
Host 請求資源所在的服務器
If-Match 比較實體標記
If-Modified-Since 比較資源的更新時間
If-None-Match 比較實體標記
If-Range 資源未更新時發送實體Byte的范圍請求
If-Unmodified-Since 比較資源的更新時間(和If-Modified-Since相反)
Max-Forwards 最大傳輸條數
Proxy-Authorization 代理服務器需要客戶端認證
Range 實體字節范圍請求
Referer 請求中的URI的原始獲取方
TE 傳輸編碼的優先級
User-Agent HTTP客戶端程序的信息

響應首部

首部字段名 說明
Accept-Ranges 是否接受字節范圍
Age 資源的創建時間
ETag 資源的匹配信息
Location 客戶端重定向至指定的URI
Proxy-Authenticate 代理服務器對客戶端的認證信息
Retry-After 再次發送請求的時機
Server 服務器的信息
Vary 代理服務器緩存的管理信息
www-Authenticate 服務器對客戶端的認證

實體首部

首部字段名 說明
Allow 資源可支持的HTTP方法
Content-Encoding 實體的編碼方式
Content-Language 實體的自然語言
Content-Length 實體的內容大小(字節為單位)
Content-Location 替代對應資源的URI
Content-MD5 實體的報文摘要
Content-Range 實體的位置范圍
Content-Type 實體主體的媒體類型
Expires 實體過期時間
Last-Modified 資源的最后修改時間
3.2 實現客戶端訪問服務端

創建HTTP服務端

let http = require("http");
let app = http.createServer((req, res) => {// req是可讀流/res是可寫流
    // 獲取請求報文信息
    let method = req.method;// 方法
    let httpVersion = req.httpVersion;// HTTP版本
    let url = req.url;
    let headers = req.headers;
    console.log(method, httpVersion, url, headers);
    // 獲取請求體(如果請求體的數據大于64k,data事件會被觸發多次)
    let buffers = [];
    req.on("data", data => {
        buffers.push(data);
    })
    req.on("end", () => {
        console.log(Buffer.concat(buffers).toString());
        res.write("hello");
        res.end("world");
    })
})
// 監聽服務器事件
app.on("connection", socket => {
    console.log("建立連接");
});
app.on("close", () => {
    console.log("服務器關閉")
});
app.on("error", err => {
    console.log(err);
});
app.listen(3000, () => {
    console.log("server is starting on port 3000");
});

創建客戶端

let http = require("http");
let options = {
    hostname: "localhost",
    port: 3000,
    path: "/",
    method: "GET",
    // 設置實體首部 告訴服務端我當前要給你發什么樣的數據
    headers: {
        "content-Type": "application/x-www-form-urlencoded",
        "Content-Length": 15
    }
}
let req = http.request(options);
req.on("response", res => {
    res.on("data", chunk => {
        console.log(chunk.toString());
    });
});
req.end("name=js&&age=22")

然后使用node運行我們的客戶端

說了這么多,你可能已經大致了解了
從輸入URL到瀏覽器顯示頁面發生了什么,不用多說,我們再來看一下緩存

4. 緩存 4.1 緩存作用

減少了冗余的數據傳輸,節省了網費。

減少了服務器的負擔, 大大提高了網站的性能

加快了客戶端加載網頁的速度

4.2 緩存分類
強制緩存

強制緩存:說白了就是第一次請求數據時,服務端將數據和緩存規則一并返回,下一次請求時瀏覽器直接根據緩存規則進行判斷,有就直接讀緩存數據庫,不用連接服務器;沒有,再去找服務器。

對比緩存

對比緩存,顧名思義,需要進行比較判斷是否可以使用緩存。

瀏覽器第一次請求數據時,服務器會將緩存標識與數據一起返回給客戶端,客戶端將二者備份至緩存數據庫中。

再次請求數據時,客戶端將備份的緩存標識發送給服務器,服務器根據緩存標識進行判斷,判斷成功后,返回304狀態碼,通知* 客戶端比較成功,可以使用緩存數據。

4.3 請求流程
第一次請求,此時沒有緩存

第二次請求

從上張圖我們可以看到,判斷緩存是否可用,有兩種方式

ETag是實體標簽的縮寫,根據實體內容生成的一段hash字符串,可以標識資源的狀態。當資源發生改變時,ETag也隨之發生變化。ETag是Web服務端產生的,然后發給瀏覽器客戶端。

Last-Modified是此資源的最后修改時間,

如果客戶端在請求到的資源中發現實體首部里有Last-Modified聲明,再次請求就會在頭里帶上if-Modified-Since字段

服務端收到請求后發現if-Modified-Since字段則與被請求資源的最后修改時間進行對比

說了這么多,不如直接來實現一下緩存

通過最后修改時間來判斷緩存是否可用

let http = require("http");
let url = require("url");
let path = require("path");
let fs = require("fs");
let mime = require("mime");
let app = http.createServer((req, res) => {
    // 根據url獲取客戶端要請求的文件路徑
    let { parsename } = url.parse(req.url);
    let p = path.join(__dirname, "public", "." + pathname);
    // fs.stat()用來讀取文件信息,文件最后修改時間就是stat.ctime
    fs.stat(p, (err, stat) => {
        if (!err) {
            let since = req.headers["if-modified-since"];//客戶端發來的文件最后修改時間
            if (since) {
                if (since === stat.ctime.toUTCString()) {//最后修改時間相等,讀緩存
                    res.statusCode = 304;
                    res.end();
                } else {
                    sendFile(req, res, p, stat);//最后修改時間不相等,返回新內容
                }
            } else {
                sendError(res);
            }
        }
    })
})
function sendError(res) {
    res.statusCode = 404;
    res.end();
}
function sendFile(req, res, p, stat) {
    res.setHeader("Cache-Control", "no-cache");// 設置通用首部字段 控制緩存行為
    res.setHeader("Last-Modified", stat.ctime.toUTCString());// 實體首部字段 資源最后修改時間
    res.setHeader("Content-Type", mime.getType(p) + ";charset=utf8")
    fs.createReadStream(p).pipe(res);
}
app.listen(3000, () => {
    console.log("server is starting on port 3000");
});
最后修改時間存在問題:
1. 某些服務器不能精確得到文件的最后修改時間, 這樣就無法通過最后修改時間來判斷文件是否更新了。
2. 某些文件的修改非常頻繁,在秒以下的時間內進行修改. Last-Modified只能精確到秒。
3. 一些文件的最后修改時間改變了,但是內容并未改變。 我們不希望客戶端認為這個文件修改了。
4. 如果同樣的一個文件位于多個CDN服務器上的時候內容雖然一樣,修改時間不一樣。

通過ETag來判斷緩存是否可用

ETag就是根據文件內容來判斷,說白了就是采用MD5(md5并不叫加密算法,它不可逆,應該叫摘要算法)產生信息摘要,用摘要來進行比對。

let http = require("http");
let url = require("url");
let path = require("path");
let fs = require("fs");
let mime = require("mime");
// crypto是node.js中實現加密和解密的模塊 具體詳解請自行了解
let crypto = require("crypto");
let app = http.createServer((req, res) => {
    // 根據url獲取客戶端要請求的文件路徑
    let { parsename } = url.parse(req.url);
    let p = path.join(__dirname, "public", "." + pathname);
    // fs.stat()用來讀取文件信息,文件最后修改時間就是stat.ctime
    fs.stat(p, (err, stat) => {
        let md5 = crypto.createHash("md5");//創建md5對象
        let rs = fs.createReadStream(p);
        rs.on("data", function (data) {
            md5.update(data);
        });
        rs.on("end", () => {
            let r = md5.digest("hex"); // 對文件進行md5加密
            // 下次就拿最新文件的加密值 和客戶端請求來比較
            let ifNoneMatch = req.headers["if-none-match"];
            if (ifNoneMatch) {
                if (ifNoneMatch === r) {
                    res.statusCode = 304;
                    res.end();
                } else {
                    sendFile(req, res, p, r);
                }
            } else {
                sendFile(req, res, p, r);
            }
        });
    })
});
function sendError(res) {
    res.statusCode = 404;
    res.end();
}
function sendFile(req, res, p, stat) {
    res.setHeader("Cache-Control", "no-cache");// 設置通用首部字段 控制緩存行為
    res.setHeader("Etag", r);// 響應首部字段 資源的匹配信息
    res.setHeader("Content-Type", mime.getType(p) + ";charset=utf8")
    fs.createReadStream(p).pipe(res);
}
app.listen(3000, () => {
    console.log("server is starting on port 3000");
});
最后

想深入學習http的同學,我推薦一本書《圖解HTTP》。
本人水平有限,有不足之處,望大家指出改正。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94579.html

相關文章

  • 前端開發應屆生面試指南(含各大公司具體指南面試真題)

    摘要:先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學,大學期間開始自學前端開發,在今年春招實習和秋招的時候投了一些公司,拿到一些京東拼多多虎牙等,總體來說還算滿意,特地寫一篇文章來總結一下面試的那些套路。 showImg(https://segmentfault.com/img/remote/1460000011897700); 先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學...

    sunnyxd 評論0 收藏0
  • 前端開發應屆生面試指南(含各大公司具體指南面試真題)

    摘要:先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學,大學期間開始自學前端開發,在今年春招實習和秋招的時候投了一些公司,拿到一些京東拼多多虎牙等,總體來說還算滿意,特地寫一篇文章來總結一下面試的那些套路。 showImg(https://segmentfault.com/img/remote/1460000011897700); 先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學...

    jeyhan 評論0 收藏0
  • 前端開發應屆生面試指南(含各大公司具體指南面試真題)

    摘要:先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學,大學期間開始自學前端開發,在今年春招實習和秋招的時候投了一些公司,拿到一些京東拼多多虎牙等,總體來說還算滿意,特地寫一篇文章來總結一下面試的那些套路。 showImg(https://segmentfault.com/img/remote/1460000011897700); 先介紹一下本人應屆前端開發一枚,非科班出身,專業是化學...

    lentoo 評論0 收藏0
  • PHPer面試指南-Web 篇

    摘要:擴展閱讀收集的前端面試題和答案前端開發面試題史上最全的前端面試題匯總及答案前端工程師手冊協議工作原理協議運行機制的概述 本書的 GitHub 地址:https://github.com/todayqq/PH... 對于大公司,很少會有全棧工程師這個崗位,全棧是個花哨的詞,對于現在比較熱門的技術,不論是 Vue 還是 Laravel,只要智商不差,看著文檔,都能寫出一個 CURD 來,...

    cnio 評論0 收藏0
  • PHPer 面試指南-擴展閱讀資源整理

    摘要:前端篇收集的前端面試題和答案前端開發面試題史上最全的前端面試題匯總及答案前端工程師手冊協議工作原理協議運行機制的概述協議篇原理原理解析的工作原理與的區別理解后端篇年的面試總結垃圾回收機制面向對象設計淺談說清楚是什么和的區別索引原理及慢查 前端篇 收集的前端面試題和答案 前端開發面試題 史上最全的web前端面試題匯總及答案 前端工程師手冊 HTTP協議:工作原理 SSL/TLS協議運行...

    wemall 評論0 收藏0
  • PHPer面試指南-協議篇

    摘要:地址每次面試多多少少都會被問到等等之類協議,協議相關的問題也可以說是面試必備,所以我把這些知識單獨收集成了一篇文章。即標志位和標志位均為。發送完畢后,服務器端進入狀態。認證服務器對客戶端進行認證以后,確認無誤,同意發放令牌。 Git 地址:https://github.com/todayqq/PH... 每次面試多多少少都會被問到 HTTP、HTTPS、TCP、Socket、 OAu...

    megatron 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<