CSS3 邊框
CSS3,你可以創建圓角邊框,添加陰影框,并作為邊界的形象而不使用設計程序,如Photoshop。
在這里邊您將了解以下的邊框屬性:
border-radius
box-shadow
border-image
CSS3 圓角
在CSS2中添加圓角棘手。我們不得不在每個角落使用不同的圖像。
在CSS3中,很容易創建圓角。
在CSS3中border-radius屬性被用于創建圓角:
這是圓角邊框!
實例
在div中添加圓角元素:
div
{
border:2px solid;
border-radius:25px;
}
CSS3盒陰影
CSS3中的box-shadow屬性被用來添加陰影:
實例
在div中添加box-shadow屬性
div
{
box-shadow: 10px 10px 5px #888888;
}
CSS3邊界圖片
有了CSS3的border-image屬性,你可以使用圖像創建一個邊框:
border-image屬性允許你指定一個圖片作為邊框! 用于創建上文邊框的原始圖像:
在div中使用圖片創建邊框:
實例
在div中使用圖片創建邊框
div
{
border-image:url(border.png) 30 30 round;
-webkit-border-image:url(border.png) 30 30 round; /* Safari 5 and older */
-o-border-image:url(border.png) 30 30 round; /* Opera */
}
新邊框屬性
屬性 | 說明 | CSS |
---|
border-image | 設置所有邊框圖像的速記屬性。 | 3 |
border-radius | 一個用于設置所有四個邊框- *-半徑屬性的速記屬性 | 3 |
box-shadow | 附加一個或多個下拉框的陰影 | 3 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
加一個簡單的陰影
讓我們為投影準備一個簡單的HTML元素:
然后添加CSS:
輸出結果是三個框,通過調用每個框的ID可以很容易地放置陰影。要添加陰影,讓我們將屬性box-shadow賦予框1:
我們提供三個參數。前兩個參數是offset-x和offset-y。兩者都確定投影的位置。相對于元素左上角的位置給出偏移量。偏移x處的正值表示將陰影向右引導,偏移y處的正值表示將陰影向下引導。
第三個參數是所需的陰影顏色。盡管這里我們使用elements <div>,但是屬性box-shadow可以應用于所有其他HTML元素。
賦予模糊半徑
如果想要陰影看起來更逼真,則可以使用blur-radius參數。此參數將設置我們如何給予陰影模糊效果。讓我們將其應用于方框2:
注意第三個參數,該值4px調整應用于投影的模糊半徑。
提供半徑差數
如果要調整陰影的大小,我們可以添加參數spread-radius以使陰影擴大或縮小。讓我們8px在框2中添加一個半徑擴展:
注意參數的順序。
合并多個陰影
我們甚至可以一次將多個陰影組合到一個元素中。讓框3應用藍色和綠色投影:
制作陰影
我們可以用參數制作一個向內的陰影inset。參數inset可以寫在屬性的開頭或結尾box-shadow。以下示例使用elements blockquote。
我們還可以添加一些模糊和散布以增強陰影:
使用properties box-shadow,我們可以為所創建的網頁提供陰影,從而可以提供良好的3D照明效果。
我們向瀏覽器的地址欄輸入URL的時候,網絡會進行一系列的操作,最終獲取到我們所需要的文件,如何交給瀏覽器進行渲染
我們所關注的問題也就是:
大致的執行順序
- URL解析
- DNS 解析:緩存判斷 + 查詢IP地址
- TCP 連接:TCP 三次握手
- SSL/TLS四次握手(只有https才有這一步)
- 瀏覽器發送請求
- 服務器響應請求并返回數據
- 瀏覽器解析渲染頁面
- 斷開連接:TCP 四次揮手
URL解析
瀏覽器先會判斷輸入的字符是不是一個合法的URL結構,如果不是,瀏覽器會使用搜索引擎對這個字符串進行搜索
URL結構組成
https://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#anchor
- 協議:https:// 互聯網支持多種協議,必須指明網址使用哪一種協議,默認是 HTTP 協議。 也就是說,如果省略協議,直接在瀏覽器地址欄輸入www.example.com,那么瀏覽器默認會訪問http://www.example.com。 HTTPS 是 HTTP 的加密版本,出于安全考慮,越來越多的網站使用這個協議。
- 主機:www.example.com 主機(host)是資源所在的網站名或服務器的名字,又稱為域名。上例的主機是www.example.com。 有些主機沒有域名,只有 IP 地址,比如192.168.2.15。
- 端口:https:// 同一個域名下面可能同時包含多個網站,它們之間通過端口(port)區分。 “端口”就是一個整數,可以簡單理解成,訪問者告訴服務器,想要訪問哪一個網站。 默認端口是80,如果省略了這個參數,服務器就會返回80端口的網站。 端口緊跟在域名后面,兩者之間使用冒號分隔,比如www.example.com:80。
- 路徑:/path/to/myfile.html 路徑(path)是資源在網站的位置。比如,/path/index.html這個路徑,指向網站的/path子目錄下面的網頁文件index.html 互聯網的早期,路徑是真實存在的物理位置?,F在由于服務器可以模擬這些位置,所以路徑只是虛擬位置 路徑可能只包含目錄,不包含文件名,比如/foo/,甚至結尾的斜杠都可以省略 這時,服務器通常會默認跳轉到該目錄里面的index.html文件(即等同于請求/foo/index.html),但也可能有其他的處理(比如列出目錄里面的所有文件),這取決于服務器的設置 一般來說,訪問www.example.com這個網址,很可能返回的是網頁文件www.example.com/index.html
- 查詢參數:?key1=value1&key2=value2 查詢參數(parameter)是提供給服務器的額外信息。參數的位置是在路徑后面,兩者之間使用?分隔 查詢參數可以有一組或多組。每組參數都是鍵值對(key-value pair)的形式,同時具有鍵名(key)和鍵值(value),它們之間使用等號(=)連接。比如,key1=value就是一個鍵值對,key1是鍵名,value1是鍵值 多組參數之間使用&連接,比如key1=value1&key2=value2
- 錨點:#anchor 錨點(anchor)是網頁內部的定位點,使用#加上錨點名稱,放在網址的最后,比如#anchor 瀏覽器加載頁面以后,會自動滾動到錨點所在的位置 錨點名稱通過網頁元素的id屬性命名
DNS解析
DNS(Domain Names System),域名系統,是互聯網一項服務,是進行域名和與之相對應的 IP 地址進行轉換的服務器
第一步:緩存判斷
判斷是正確的URL格式之后,DNS會在我們的緩存中查詢是否有當前域名的IP地址
基本步驟:
- 瀏覽器緩存:瀏覽器檢查是否在緩存中
- 操作系統緩存:操作系統DNS緩存,去本地的hosts文件查找
- 路由器緩存:路由器DNS緩存
- ISP 緩存: ISP DNS緩存(ISP DNS 就是在客戶端電腦上設置的首選 DNS 服務器,又稱本地的DNS服務器)
在經歷上述緩存查找還沒有找到的話,就進行下一步查詢操作
第二步:查詢IP地址
瀏覽器會去根域名服務器中查找,如果還沒有就去頂級域名服務器中查找,最后是權威域名服務器。
找到IP地址后,將它記錄在緩存中,供下次使用。
TCP連接:三次握手
簡單理解
簡單的理解就是:
客戶端:hello,你好,你是server嗎?
服務端:hello,你好,我是server,你是client嗎
客戶端:yes,我是client
開始數據傳輸.....
——————————————————————————————————————————
客戶端(男人):我喜歡你,咱倆處對象吧
服務端(女人):我也喜歡你,我答應你
客戶端(男人):太棒了,我們現在去看電影吧
開始數據傳輸.....
然后雙方就正確建立連接,開始傳輸數據
詳細分析
- 第一次握手:客戶端發送一個帶 SYN=1,Seq=x 的數據包到服務器端口 第一次握手,由瀏覽器發起,告訴服務器我要發送請求了 SYN(synchronous):請求建立連接 seq(sequence):隨機序列號 請注意TCP規定SYN被設置為1的報文段不能攜帶數據但要消耗掉一個序號。
- 第二次握手:服務器發回一個帶 SYN=1, ACK=1, seq=y, ack=x+1 的響應包以示傳達確認信息 第二次握手,由服務器發起,告訴客戶端我準備接受了,你趕緊發送吧 ACK(acknowledgement):確認,是一個確定字符 ack:ack=上一次的seq+1,作用是接受上一次遠端主機傳來的seq,加一然后再傳給客戶端,提示客戶端已經成功接收上一次所有數據 請注意這個報文段不能攜帶數據,因為它是SYN被設置為一的報文段但同樣要消耗掉一個序號
- 第三次握手:客戶端再回傳一個帶 ACK,seq=x + 1, ack=y + 1 的數據包,代表“握手結束” 第三次握手,由瀏覽器發送,告訴服務器,我馬上就發了,準備接受吧 確認報文段可以攜帶數據。但如果不攜帶數據則不消耗序號,在這種情況下所發送的下一個數據報文段的序號仍是x + 1
然后雙方就正確建立連接,開始傳輸數據
SSL/TLS四次握手
HTTPS 建立連接的過程,先進行 TCP 三次握手,再進行 TLS 四次握手(僅對https)
因為 HTTPS 都是基于 TCP 傳輸協議實現的,得先建立完可靠的 TCP 連接才能做 TLS 握手的事情。
第一次握手:客戶端發出請求Client Hello
- 首先,客戶端先向服務器發出加密通信的請求,這被叫做clienthello請求。
- 在這一步,客戶端主要向服務器提供以下信息:
- 支持的協議版本,比如TLS1.0版本
- 支持的加密方法,比如RSA公鑰加密
- 一個客戶端生成的隨機數(client random), 稍后用于生成對話密鑰(session key)
第二次握手:服務器回應Server Hello
- 服務器收到客戶端請求后,向客戶端發出回應,這叫做serverhello
- 這一步服務器主要干三件事:
- 確認使用的加密通信協議版本,比如TLS1.00版本。如果游覽器與服務器支持的版本不一致,服務器關閉加密通信
- 確認使用的加密方法(客戶端所支持),比如RSA公鑰加密
- 將服務器證書、非對稱加密的公鑰,以及一個隨機數(Server random)發送給客戶端游覽器
客戶端驗證證書
客戶端收到服務器回應以后,首先驗證服務器證書,驗證手段就是執行如下三種檢查:
- 檢查證書是否已過期;
- 檢查證書中的域名與實際域名是否一致
- 檢查證書是否是可信機構頒布的
如果,上述過程中有任何一個環節發現問題,那么瀏覽器就會向訪問者顯示一個警告,由其選擇是否還要繼續通信。如果證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串新的隨機數(Premaster secret )。
第三次握手:客戶端回應
此時,瀏覽器會根據前三次握手中的三個隨機數:
- Client random
- Server random
- Premaster secret
通過一定的算法來生成 “會話密鑰” (Session Key),這個會話密鑰就是接下來雙方進行對稱加密解密使用的密鑰!
第四次握手:服務端回應
服務端收到客戶端的回復,利用已知的加密解密方式進行解密,服務器收到客戶端的第三個隨機數( Premaster secret) 之后,使用同樣的算法計算出 “會話密鑰” (Session Key)。
至此,整個握手階段全部結束。接下來,客戶端與服務器進入加密通信,就完全是使用普通的 HTTP 協議,只不過用 “會話密鑰” 加密內容。(非對稱加密解密將不再使用,接下來完全由對稱加密接手了,因為密鑰已經安全的傳送給了通信的雙方)
總結
- 客戶端請求建立SSL鏈接,并向服務發送一個隨機數–Client random和客戶端支持的加密方法,比如RSA公鑰加密,此時是明文傳輸
- 服務端回復一種客戶端支持的加密方法、一個隨機數–Server random、授信的服務器證書和非對稱加密的公鑰
- 客戶端收到服務端的回復后利用服務端的公鑰,加上新的隨機數–Premaster secret 通過服務端下發的公鑰及加密方法進行加密,發送給服務器
- 服務端收到客戶端的回復,利用已知的加解密方式進行解密,同時利用Client random、Server random和Premaster secret通過一定的算法生成HTTP鏈接數據傳輸的對稱加密key – session key
瀏覽器發送請求
連接建立成功之后,瀏覽器向服務器發送HTTP請求報文,來獲取自己想要的數據
請求報文由請求行、請求頭、空行、請求體四部分組成
- 請求行:有請求方法、請求的url、http協議及其版本
- 請求頭:把瀏覽器的一些基礎信息告訴服務器。比如包含了瀏覽器所使用的操作系統、瀏覽器內核等信息,以及當前請求的域名信息、瀏覽器端的 Cookie 信息等
- 空行:最后一個請求頭之后是一個空行,發送回車符和換行符,通知服務器以下不再有請求頭
- 請求體(報文主體/請求中文):當使用POST, PUT等方法時,通常需要客戶端向服務器傳遞數據。這些數據就儲存在請求正文中。在請求包頭中有一些與請求正文相關的信息,例如: 現在的Web應用通常采用Rest架構,請求的數據格式一般為json。這時就需要設置Content-Type: application/json。
服務端響應請求并返回數據
服務器對http請求報文進行解析,并給客戶端發送HTTP響應報文對其進行響應
HTTP響應報文也是由狀態行、響應頭、空行、響應體四部分組成
- 響應行/狀態行:由 HTTP 版本協議字段、狀態碼和狀態碼的描述文本 3 個部分組成
- 響應頭:用于指示客戶端如何處理響應體,告訴瀏覽器響應的類型、字符編碼和字節大小等信息
- 空行:最后一個響應頭部之后是一個空行,發送回車符和換行符,通知服務器以下不再有響應頭部。
- 響應體:返回客戶端所需數據
這個時候瀏覽器拿到我們服務器返回的HTML文件,可以開始解析渲染頁面
瀏覽器解析渲染頁面
當我們經歷了上述的一系列步驟之后,我們的瀏覽器就拿到了我的HTML文件那么它又是如何解析整個頁面并且最終呈現出我們的網頁呢?
渲染流程圖
簡圖:從這張圖上我們可以得出一個重要的結論:下載CSS文件并不會阻塞HTML的解析
詳圖:
詳細解析步驟
解析一:HTML解析過程
默認情況下服務器會給瀏覽器返回index.html文件,所以解析HTML是所有步驟的開始:解析HTML,會 構建DOM Tree
當遇到我們的script文件的時候,我們是不能進行去構建DOM Tree的。它會停止繼續構建,首先下載JavaScript代碼,并且執行JavaScript的腳本,只有等到JavaScript腳本執行結束后,才會繼續解析HTML,構建DOM樹。
具體的相關細節看下面的script與頁面解析
解析二:生成CSS規則
- 在解析的過程中,如果遇到CSS的link元素,那么會由瀏覽器負責下載對應的CSS文件
- 瀏覽器下載完CSS文件后,就會對CSS文件進行解析,解析出對應的規則樹
- 我們可以稱之為 CSSOM (CSS Object Model,CSS對象模型)
解析三:構建Render Tree
當有了 DOM Tree 和 CSSOM Tree 后,就可以兩個結合來 構建 Render Tree
- 注意一:link元素不會阻塞DOM Tree的構建過程,但是會阻塞Render Tree的構建過程
- 因為Render Tree在構建時,需要對應的CSSOM Tree。當我們DOMTree解析完成的時候,如果CSSOM Tree沒解析完成就會阻塞。當然一般情況下瀏覽器會進行優化處理,不會傻傻的等待
- 注意二:Render Tree和DOMTree并不是一一對應的關系
- 比如對于display為none的元素,壓根不會出現在render tree中
解析四:布局(layout)和繪制(Paint)
- 第四步是在**渲染樹(Render Tree)**上運行 布局(Layout) 以計算每個節點的幾何體。 渲染樹會 表示 要顯示哪些節點以及其他樣式,但是 不表示 每個節點的尺寸、位置 等信息 布局的主要目的是為了確定呈現樹中所有節點的寬度、高度和位置信息
- 第五步是將每個節點 繪制(Paint) 到屏幕上 在繪制階段,瀏覽器將布局階段計算的 每個frame轉為屏幕上實際的像素點 包括 將元素的可見部分進行繪制,比如文本、顏色、邊框、陰影、替換元素(比如img)
特殊解析:composite合成
- 繪制的過程,可以將布局后的元素繪制到多個合成圖層中【這是瀏覽器的一種優化手段】
- 默認情況下,標準流中的內容都是被繪制在同一個圖層(Layer)中的
- 而一些特殊的屬性,會創建一個新的合成層(Compositinglayer ),并且新的圖層可以利用GPU來加速繪制
- 那么哪些屬性可以形成新的合成層呢?常見的一些屬性:
- 3D transforms
- video、canvas、iframe
- opacity動畫轉換時
- position: fixed
- will-change:一個實驗性的屬性,提前告訴瀏覽器元素可能發生哪些變化
- animation或 transition設置了opacity、transform
- 分層確實可以提高性能,但是它以內存管理為代價,因此不應作為web性能優化策略的一部分過度使用
其他相關概念
回流
- 回流reflow(也可以稱之為重排) 第一次確定節點的大小和位置,稱之為布局(layout) 之后對節點的大小、位置修改 重新計算 稱之為回流
- 什么情況下引起回流呢? 比如DOM結構發生改變(添加新的節點或者移除節點) 比如改變了布局(修改了width、height、padding、font-size等值) 比如窗口resize(修改了窗口的尺寸等) 比如調用getComputedStyle方法獲取尺寸、位置信息
重繪
- 重繪repaint【字面理解就是對頁面再做繪制】 第一次渲染內容稱之為繪制(paint) 之后重新渲染稱之為重繪
- 什么情況下會引起重繪呢? 比如修改背景色、文字顏色、邊框顏色、樣式等
聯系
- 回流一定會引起重繪,所以回流是一件很消耗性能的事情。
- 所以在開發中要盡量避免發生回流 修改樣式時盡量一次性修改【比如通過cssText修改,比如通過添加class修改】 盡量 避免頻繁的操作DOM【我們可以在一個DocumentFragment或者父元素中將要操作的DOM操作完成,再一次性的操作】 盡量 避免通過getComputedStyle獲取尺寸、位置等信息 對某些元素使用position的absolute或者fixed【并不是不會引起回流,而是開銷相對較小,不會對其他元素造成影響】
script元素
script元素和頁面聯系
- 我們現在已經知道了頁面的渲染過程,但是JavaScript在哪里呢? 事實上,瀏覽器在解析HTML的過程中,遇到了 script元素是不能繼續構建DOM樹的 它會 停止繼續構建,首先下載JavaScript代碼,并且執行JavaScript的腳本 只有 等到JavaScript腳本執行結束后,才會繼續解析HTML,構建DOM樹
- 為什么要這樣做呢? 這是 因為JavaScript的作用之一就是操作DOM,并且可以修改DOM 如果我們等到DOM樹構建完成并且渲染再執行JavaScript會造成嚴重的回流和重繪,影響頁面的性能 所以會在遇到script元素時,優先下載和執行JavaScript代碼,再繼續構建DOM樹
- 但是這個也往往會帶來新的問題,特別是現代頁面開發中: 在目前的開發模式中(比如Vue、React),腳本往往比HTML頁面更“重”,處理時間需要更長 所以會造成頁面的解析阻塞,在腳本下載、執行完成之前,用戶在界面上什么都看不到
- 為了解決這個問題,script元素給我們提供了兩個屬性(attribute) : defer和async
defer屬性
- defer屬性告訴瀏覽器 不要等待腳本下載,而繼續解析HTML,構建DOM Tree
- 腳本會 由瀏覽器來進行下載,但是不會阻塞DOM Tree的構建過程
- 如果腳本提前下載好了,它會 等待DOM Tree構建完成,在DOMContentLoaded事件之前先執行defer中的代碼
- 所以DOMContentLoaded總是會等待defer中的代碼先執行完成
<script src="./foo.js" defer></script>
<script>
window.addEventListener("DOMContentLoaded",()=>{
console.log("DOMContentLoaded");
})
</script>
- 多個帶defer的腳步是可以保持正確的執行順序的
- 從某種角度來說,defer可以提高頁面的性能,并且推薦放到head元素中
- 注意:defer僅適用于外部腳本,對于script默認內容會被忽略
async屬性
- async特性與defer有些類似,它也能夠讓腳本不阻塞頁面
- async是讓一個腳本完全獨立的:
- 瀏覽器 不會因async 腳本而阻塞(與defer類似)
- async腳本不能保證順序,它是獨立下載、獨立運行,不會等待其他腳本
- async不會能保證在DOMContentLoaded之前或者之后執行
- defer通常用于需要在文檔解析后操作DOM的JavaScript代碼,并且對多個script文件有順序要求的
- async通常用于獨立的腳本,對其他腳本,甚至DOM沒有依賴的
斷開連接:TCP 四次揮手
在渲染完成后,瀏覽器可能會繼續加載頁面中的其他資源,如異步加載的內容或者通過JavaScript生成的動態內容。
而在此過程中,如果沒有其他資源需要加載,瀏覽器將與服務器之間的TCP連接斷開。
簡單理解
復制代碼主動方:我已經關閉了向你那邊的主動通道了,這是我最后一次給你發消息了,之后只能被動接收你的信息了
被動方:收到你通道關閉的信息
被動方:那我也告訴你,我這邊向你的主動通道也關閉了
主動方:最后收到你關閉的信息,OK結束
斷開連接,結束通訊
————————————————————————————————————————————————————————————————————————————
提出分手的可能是男生(客戶端),也可能是女生(服務端)
主動方:分手吧,我不喜歡你了!
被動方:行,你等我忙完手上的工作我在收拾你!
被動方:我忙完了,分手就分手!
主動方:好,好聚好散,拜拜!
斷開連接,結束通訊
詳細分析
由于TCP連接是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成數據發送任務后,發送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。
任何一方都可以在數據傳送結束后發出連接釋放的通知,所有主動發起關閉請求可以是客戶端,也可以是服務端
這里我們假設是由客戶端先主動發起關閉請求
- 第一次揮手:TCP客戶進程會發送TCP連接釋放報文段,并進入終止等待1(FIN-WAIT-1)狀態。 FIN:終止位,表示斷開TCP連接 TCP規定終止位FIN等于1的報文段即使不攜帶數據,也要消耗掉一個序號
- 第二次揮手:TCP服務器進程收到TCP連接釋放報文段后,會發送一個普通的TCP確認報文段并進入關閉等待(CLOSE-WAIT)狀態。 序號seq字段的值設置為v,與之前收到的TCP連接釋放報文段中的確認號匹配 TCP客戶進程收到TCP確認報文段后就進入終止等待2(FIN-WAIT-2)狀態,等待TCP服務器進程發出的TCP連接釋放報文段 這時的TCP連接屬于半關閉狀態,也就是TCP客戶進程已經沒有數據要發送了。但如果TCP服務器進程還有數據要發送,TCP客戶進程仍要接收,也就是說從TCP服務器進程到TCP客戶進程這個方向的連接并未關閉,這個狀態可能要持續一段時間。
- 第三次揮手:TCP服務器進程發送TCP連接釋放報文段 假定序號seq字段的值為w,這是因為在半關閉狀態下,TCP服務器進程可能又發送了一些數據。 確認號ack字段的值為u+1,這是對之前收到的TCP連接釋放報文段的重復確認。
- 第四次揮手:TCP服務器進程收到確定報文段后就進入關閉狀態,而TCP客戶進程還要經過2MSL后才能進入關閉狀態。
之后斷開連接,結束通訊
總結
- 瀏覽器先判斷是否為合法的url格式,不合法則在搜索引擎中搜索
- 合法后,DNS解析會先判斷緩存中是否有url的ip地址。
- 緩存的查詢順序是:瀏覽器緩存 -> 操作系統緩存(本地的hosts文件) -> 路由器緩存 -> 本地的DNS服務器緩存
- 在緩存中沒有的情況,則向服務器發起請求查詢ip地址。
- 查詢IP地址的順序是:根域名服務器 -> 頂級域名服務器 -> 權威域名服務器。直到查找到返回,并將其存儲在緩存中下次使用
- TSP建立連接,也就是三次握手
- 第一次握手,攜帶建立連接請求SYN=1和隨機序列seq=x
- 第二次握手,攜帶確定字段ACK=1、連接請求SYN=1、隨機序列seq=y和ack為上一次握手的seq+1,就是x+1
- 第三次握手,攜帶確定字段ACK=1、ack=y+1、seq=x+1
- 如果是https,還有一個TLS四次握手
- 第一次握手,客戶端向服務端發送 支持的協議版本 + 支持的加密方法 + 生成的隨機數
- 第二次握手,服務端向客戶端發送 證書 + 公鑰 + 隨機數
- 第三次握手前,客戶端會先驗證證書有沒有過期、域名對不對、是否可信機構頒發的。
- 沒有問題或者用戶接受不受信的證書,瀏覽器會生成一個新的隨機數
- 第三次握手,將之前的三個隨機數通過一定的算法生成會話秘鑰,之后的加密解密都是用這個秘鑰
- 第四次握手,服務端收到回復,是用確定的加密方法進行解密,得到第三個隨機數,使用同樣的算法計算出會話秘鑰
- 建立連接之后,瀏覽器發送http請求
- 請求報文由請求行、請求頭、空行和請求體組成
- 服務器解析請求報文,返回響應報文
- 響應報文由響應行、響應頭、空行和響應體組成,我們需要的html文件就在響應體中
- 瀏覽器拿到html文件并開始解析,構建dom tree。遇到css文件,下載并構建CSSOM tree。等到兩者都構建完成之后,一起構建Render tree。然后進行布局和繪制
- 其中遇到了script標簽,則停止構建dom tree,等下載完成之后才會繼續構建dom tree
- 當資源傳輸完畢之后,TSP關閉連接,進行四次揮手的操作,其中四次揮手的操作客戶端和服務器都可以發起
- 第一次揮手,攜帶斷開連接的FIN=1、確定字段ACK=1、隨機序列seq=u,ack=v
- 第二次揮手,攜帶確定字段ACK=1、隨機序列seq=v,ack=u+1
- 第三次揮手,攜帶確定字段ACK=1、斷開連接FIN=1、隨機序列seq=w、ack=u+1
- 第四次揮手,攜帶確定字段ACK=1,隨機序列seq=u+1,ack=w+1
- 等待2MSL后進入關閉狀態
- 斷開連接,結束通訊
作者:前端實習生鯨落
鏈接:https://juejin.cn/post/7279093851000242234