前后端交互模型(一個面試題引發的思考總結)


客戶端和服務端的交互

面試題: 當用戶在地址欄中輸入網址,到最后看到頁面,中間都經歷了什么? (引出前后端交互模型的內容)

客戶端    =======>  服務端  (request請求階段)
服務端    <=======  客戶端  (responese響應階段)

1.URL地址解析
2.DNS域名解析(DNS服務器)
3.和服務器建立TCP連接  (三次握手)
4.把客戶端信息傳遞給服務器(發送HTTP請求)
5.服務器得到並處理請求(HTTP響應內容)
6.客戶端渲染服務器返回的內容
7.和服務器端斷開TCP連接(四次揮手)

 **下面分別由這7個點來展開說明**
----------------------------------------------------------------
(補充說明)服務器接收到請求后:
1.根據端口號找到對應的項目
2.根據請求資源的路徑名稱找到資源文件
3.讀取資源文件中的內容
4.把內容返回

一.URL地址解析

1.1 URI / URL / URN

URL: Uniform Resource Locator 統一資源定位符 (根據這個地址可以找到一個地方)

URN: Uniform Resource Name 統一資源名稱 (一般看不到)

URI :Uniform Resource Identifier 統一資源標識符,URL和URN是URI的子集

1.2 一個完整的URL所包含的完整的內容

http: //www.xiaohuang.cn/stu/index.html?form=wx&lx=1#zhenyu

  • 協議:http: // (傳輸協議就是,能夠把客戶端和服務器通信的信息,進行傳輸的工具,類似於快遞小哥)

    • http超文本傳輸協議
    • https更加安全的http,一般涉及支付的網站都要采用https協議(加密傳輸)
    • ftp 文件傳輸協議 (一般應用於把本地資源上傳到服務器)
  • 域名:www.xiaohuang.cn (不通過域名,直接用服務器的外網ip地址也能訪問,域名就是一個方便記憶的名字)

    • 頂級域名 :qq.com (買域名了時候,都是買頂級域名)
    • 一級域名:www.qq.com
    • 二級域名 :sports.qq.com
  • 端口號(:80):端口號的取值范圍0~65535 ,用端口號來區分同一個服務器上的不同項目

    • http默認端口號:80
    • https默認端口號: 443
    • 如果項目采用的就是默認端口號,我們在書寫地址的時候,不用加端口號,瀏覽器發送請求的時候會幫我們默認加上
  • 請求資源l路徑名稱:stu/index.html

    • 默認的路徑或者名稱(xxx.com/stu/ 不指定資源名,服務器會找默認的資源,一般默認資源名是default.html , index.html)
    • 注意偽URL地址的處理:https://item.jd.com/100005297930.html =>其實是 https://item.jd.com/index.php?id=12344 , ( URL重寫技術是為了增加SEO優化的,動態的網址一般不能被搜索引擎優化,所以我們要把動態網址靜態化)
  • 問號傳參信息:?form=wx&lx=1

    • 客戶端想把信息傳遞給服務器,有很多種方式:1.URL地址問號傳參 2.請求報文傳輸(請求頭和請求主體)
    • 也可以不同頁面之間的信息交互,例如:從列表到詳情
  • hash值:#zhenyu

    • 也能充當信息傳輸的方式
    • 錨點定位
    • 基於hash實現路由管控(不同的hash值,展示不同的組件和模塊)

1.3 URL中特殊字符編碼和解碼

請求地址中如果出現非有效UNICODE編碼內容(空格,中文,特殊字符),現代版瀏覽器會默認進行編碼

  • encodeURI / decodeURI

    • 基於encodeURI編碼,我們也可以基於decodeURI解碼 (這兩個都是window下的方法,可以直接調用,下面的方法同理)
  • encodeURIComponent / decodeURIComponent

    • encodeURIComponent / decodeURIComponent它相對於encodeURI來說,不用於給整個URL編碼,而是給URL部分信息進行編碼(一般都是問號傳值編碼)
  • escape / unescape

    • 這種方式一般只用於客戶端頁面之間自己的處理,例如:從列表跳轉到詳情,在比如如果我們在客戶端中的cookie信息,如果是中文,我們也基於這種辦法編碼
  • ....


二. DNS服務器域名解析

DNS就是域名解析服務器,這個服務器是歸全世界的(在服務器上存貯着 域名 ,服務器外網ip的相關記錄)

而我們發送請求的時候所謂的DNS解析,其實就是根據域名在DNS服務器上查找對應服務器的外網ip

拿阿里雲舉例:如何在雲服務器上完成域名和外網ip的關聯

進入域名管理界面 => 點擊解析 => 點擊添加記錄 => 1.記錄類型(ipv4就是外網ip)2.主機記錄(www)3.解析路線(默認) 4.記錄值 (服務器的具體ip地址) => 確定 (完成了在DNS域名服務器上添加了一個域名關聯某個ip地址的記錄)

2.0 釣魚網站

我們常見的釣魚網站就是,通過技術手段,模擬假DNS服務器,使用戶訪問某個官方的域名的時候,不是通過DNS服務的解析訪問正常ip地址,而是黑客自身的ip地址,然后記錄釣魚網站用戶輸入的用戶名和密碼

2.1 DNS優化

  • DNS緩存(一般瀏覽器會在第一次解析后,默認建立緩存,事件很短,只有一分鍾左右)

    • <head>
          <meta charset="UTF-8">
          <!-- DNS預獲取 -->
          <meta http-equiv="x-dns-prefetch-control" content="on">
          <link rel="dns-prefetch" href="//static.360buyimg.com">
          <link rel="dns-prefetch" href="//misc.360buyimg.com">
      </head>
      
      DNS預獲取:在頁面加載開始的時候,就把當前頁面中需要訪問其他域名(服務器)的信息進行提前DNS解析,以后加載到具體內容部分就不同解析了
      
  • 減少DNS解析次數(一個網站中我們需要發送請求的域名和服務器盡可能少即可)


三.建立TCP連接(三次握手)

用大白話來說:

  • 第一次握手:有瀏覽器發起,告訴服務器我要發送請求了
  • 第二次握手:有服務器發起,告訴瀏覽器我准備接受了,你趕緊發把
  • 第三次握手: 由瀏覽器發送,告訴服務器,我馬上就發了,准備接受把

具體:

  • 第一次,瀏覽器發送:SYN=1 seq=J (這個J是自定義也可以是A。。)
  • 第二次,服務器返回:SYN=1 ACK=1 ack = J+1 ,seq=K
  • 第三次, 瀏覽器發送:ACK=1 ack=K+1

就是通過簡單的三次握手,用代碼的方式,表達能夠相互通信 (就是在真正發送請求之前,臨時驗證能否正常通信,建立好通信通道)


四.發送HTTP請求

就是把需要發送的數據,通過建立的TCP通道,傳輸到服務器 (TCP類比通道,HTTP類比快遞員)

4.1 HTTP請求報文

  • 起始行
  • 請求頭 Headers(首部)
  • 請求主體

4.2 強緩存 和 協商緩存

這部分另外單獨分析

  • 強緩存 (Cache-Control 和 Expires)
  • 協商緩存 (Last - Modified 和 Etag)

五.服務器響應HTTP內容

一般來說,web服務器和數據服務器在同一個服務器的相同服務下(協議,域名,端口都一致),這種就是同源策略請求 =>AJAX , 但是在真實項目中往往兩台服務器是分開的,此時是非同源策略請求 =>跨域

5.1 WEB(圖片)服務器和數據服務器

  • Tomcat
  • Nginx
  • Apache
  • IIS

5.2 HTTP響應報文

2XX 成功:響應代碼表明操作成功了。

3XX 重定向:客戶端需要做些額外工作才能得到所需要的資源。它們通常用於GET請求。他們通常告訴客戶端需要向另一個URI發送GET請求,才能得到所需的表示。那個URI就包含在Location響應報頭里

4XX 客戶端錯誤:這些響應代碼表明客戶端出現錯誤。不是認證信息有問題,就是表示格式或HTTP庫本身有問題。客戶端需要自行改正。

5XX 服務端錯誤: 這些代碼意味着服務器處於不能執行客戶端請求的狀態,此時客戶端應稍后重試。有時,服務器能夠估計客戶端應在多久之后重試。並把該信息放在Retry-After響應報頭里。

  • 響應狀態碼
    • 200 ok: 成功
    • 201 created: 一般應用於告訴服務器創建一個新文件,最后服務器創建成功后返回的狀態碼
    • 204 no content:對於某些請求(例如:put或者delete),服務器不想處理,可以返回空內容,並且用204狀態碼告知
    • 301 :永久重定向(永久轉移) 讓客戶端使用另外一個url來請求資源
    • 302 :臨時轉移,很早以前基本上用302來做,但是現在主要用307來處理這個事情,307的意思就是臨時重定向=> 主要用於:服務器的負載均衡 等
    • 304 :設置HTTP的協商緩存
    • 400 :傳遞給服務器的參數錯誤
    • 401:無權限訪問
    • 404: 請求地址錯誤
    • 500:未知服務器錯誤
    • 503:服務器超負荷
  • 響應頭(首部)
  • 響應主體

六.客戶端渲染頁面

瀏覽器渲染頁面的時候,遇到link / img /audio / video 等是異步去加載資源信息 (瀏覽器分配一個新的線程去加載,主線程繼續向下渲染頁面),如果遇到script或者@import,則讓主線程去加載資源信息 (同步),加載完成信息之后,在去渲染頁面

6.1 瀏覽器渲染頁面的步驟

  • 解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
  • 將DOM樹結合CSSOM樹結合,生成渲染樹(Render Tree)
  • Layout(回流):根據生成的渲染樹,計算它們在設備視口(viewport)內的確切位置和大小,這個階段是回流
  • Painting(重繪): 根據渲染以及回流得到的幾何信息,得到節點的絕對像素
  • Display:將像素發送給GPU, 展示到頁面上

6.2DOM的重繪與回流

  • 重繪:元素樣式(顏色)的改變(但寬高,大小,位置不變)
  • 回流:元素的大小或者位置發生了變化(當頁面布局和幾何信息發生變化的時候),觸發了重新布局,導致渲染樹重新計算布局和渲染
  • 注意:回流一定會觸發重繪,而重繪不一定會回流

6.3 前端性能優化之:避免DOM的回流

  • 放棄傳統操作dom的時代,基於vue/react開始數據影響視圖模式(因為操作dom必然是會觸發回流)
  • 分離讀寫操作(現代的瀏覽器都有渲染隊列的機制)
    • =>現代瀏覽器都有"隊列機制":發現某一行要修改元素的樣式,不立即渲染,而是看看下一行,如果下一行也會改變樣式,則把修改樣式的操作放到"渲染隊列中"...一直到不是修改樣式后的操作后,整體渲染一次,引發一次回流
    • 當我們獲取一些樣式的時候,如box.offsetWidth(偏移量,盒子寬度等),會刷新渲染隊列,所以我們在設置樣式和獲取樣式的時候,應該集中書寫,而不是交叉書寫,做到讀寫分離
  • 樣式集中改變
  • 緩存布局信息
    • 當我們需要多次修改某個屬性的時候,不應該獲取到了之后直接修改,應該用一個變量存貯獲取到的值,再來進行修改 (原理就是讀寫分離)
  • 元素批量修改
    • 案例說明:當我們需要往一個盒子中插入10個盒子的時候,錯誤:循環10次插入(引發回流重繪),正確:使用模板字符串,循環10次,將所有盒子集中到一個字符串中,一次性插入到dom樹當中
    • 使用文檔碎片(存儲文檔的容器),先插入到文檔碎片中,最后將文檔碎片插入到頁面當中
  • 動畫效果應用到position屬性為absolute或fixed元素上(脫離文檔流)
  • css3硬件加速(GPU加速)
  • 犧牲平滑度換取速度
  • 避免table布局和使用css的javascript表達式

七. 斷開連接(四次揮手)

四次揮手,是發生在信息的傳輸過程中,三次揮手,是發生在信息傳出之前的

  • 第一次揮手:由瀏覽器發起,發送給服務器,我請求報文發送完了,你准備關閉把
  • 第二次揮手:由服務器發起,告訴瀏覽器,我接受完請求報文了,我准備關閉,你也准備把
  • 第三次揮手:由服務器發起,告訴瀏覽器,我響應報文發送完畢,你准備關閉把
  • 第四次揮手:由瀏覽器發起,告訴服務器,我響應報文接受完畢,我准備關閉,你也准備把

真實傳輸:

  • 第一次:瀏覽器發出 FIN M
  • 第二次: 服務器發出 ack M+1
  • 第三次: 服務器再次發出 FIN K
  • 第四次:瀏覽器發出 ACK=1 ack=K+1

7.1 connection:Keep-Alive 保持TCP不中斷(在請求報文中設置)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM