將USB設(shè)備使用情況看個清楚
在電腦中插入了USB設(shè)備并被移除之后,會在系統(tǒng)中留下什么痕跡嗎?如果我們需要了解USB設(shè)備在本系統(tǒng)中曾經(jīng)或正在使用的情況,可以用USBDeview這款小軟件來查明。
文|如云
利用USBDeview(下載地址:http://www.nirsoft.net/utils/usbdeview.zip或http://www.nirsoft.net/utils/usbdeview-x64.zip,為32位和64位兩種程序),我們可以列出當(dāng)前連接到電腦或曾連接過該電腦的所有USB設(shè)備。該軟件不用安裝,下載并解包后直接運行EXE程序即可啟動。
啟動軟件后,窗口中會列出所有在該系統(tǒng)插入或插入過并被記錄下來的USB設(shè)備的信息,記錄的項目達40種之多。其中主要項目有:“Device Name”為設(shè)備名稱、“Description”為設(shè)備描述、“Device Type”為設(shè)備類型、“Connected”為是否已連接、“Safe To Unplug”為是否支持安全拔插、“Serial Number”為設(shè)備序列號、“Registry Time 1”為設(shè)備最近添加時間、“Registry Time 2”為設(shè)備上次連接時間、“Firmware Revision”為設(shè)備固件版本、“Hub/Port”為連接的Hub和端口編號、“Driver Filename”為設(shè)備驅(qū)動程序名稱、“Driver InfPath”為設(shè)備驅(qū)動信息文件路徑。從這些信息中,我們便可以看出是什么樣的設(shè)備在什么時間連接了哪個端口,設(shè)備型號、驅(qū)動程序以及其他具體屬性如何等情況。
如果需要斷開某個設(shè)備的連接,只需在選中該設(shè)備條目后點擊工具欄中的紅寶石按鈕,這時“Disabled”一欄將顯示“Yes”;重新連接點擊綠寶石按鈕;點擊藍寶石按鈕則是斷開后再立即自動連接,相當(dāng)于刷新一下設(shè)備的連接。
當(dāng)需要卸載列表中的某個設(shè)備時,選中該設(shè)備并點擊工具欄中的垃圾桶圖標(biāo)即可;或者也可以通過右鍵菜單選擇“Uninstall Selected Devices”。
設(shè)備的右鍵菜單是一個比較萬能的操作渠道,在其中我們不僅可以完成上述的設(shè)備斷開、連接、重新連接等動作,還可以創(chuàng)建設(shè)備的桌面快捷方式、打開相關(guān)設(shè)備、自動播放、打開注冊表相關(guān)選項、打開設(shè)備INF文件、查看設(shè)備屬性等。我們還可以通過右鍵菜單命令測試連接某些設(shè)備的讀/寫速度。
如果需要將選定的設(shè)備列表導(dǎo)出為文本/HTML或XML格式,可以選擇“HTML Report - Selected Iterms”菜單命令操作,“HTML Report - All Iterms”為導(dǎo)出所有選項;或者直接點擊工具欄中的磁盤按鈕。導(dǎo)出的格式還可以是TXT、CSV等。
該程序還支持通過命令行來操作。具體參數(shù)的使用以及命令案例,請參閱主程序目錄中的USBDeview.chm幫助文件。
此外,“Options”菜單中有許多有用的選項,如隱藏啟動、置頂、退縮到任務(wù)欄等。CF
疊樣式表(Cascading Style Sheet,簡稱:CSS)是為網(wǎng)頁添加樣式的代碼。本節(jié)將介紹 CSS 的基礎(chǔ)知識,并解答類似問題:怎樣將文本設(shè)置為黑色或紅色?怎樣將內(nèi)容顯示在屏幕的特定位置?怎樣用背景圖片或顏色來裝飾網(wǎng)頁?
CSS 究竟什么來頭?
和 HTML 類似,CSS 也不是真正的編程語言,甚至不是標(biāo)記語言。它是一門樣式表語言,這也就是說人們可以用它來選擇性地為 HTML 元素添加樣式。舉例來說,要選擇一個 HTML 頁面里所有的段落元素,然后將其中的文本改成紅色,可以這樣寫 CSS:
p {
color: red;
}
不妨試一下:首先新建一個 styles 文件夾,在其中新建一個 style.css 文件,將這三行 CSS 保存在這個新文件中。
然后再將該 CSS 文件連接至 HTML 文檔,否則 CSS 代碼不會對 HTML 文檔在瀏覽器里的顯示效果有任何影響。(如果你沒有完成前幾節(jié)的實踐,請復(fù)習(xí)處理文件 和 HTML 基礎(chǔ)。在筆記本里有這個方面的內(nèi)容!)
1、打開 index.html 文件,然后將下面一行粘貼到文檔頭(也就是 <head> 和 </head> 標(biāo)簽之間)。
<link href="styles/style.css" rel="stylesheet">
2、保存 index.html 并用瀏覽器將其打開。應(yīng)該看到以下頁面:
如果段落文字變紅,那么祝賀你,你已經(jīng)成功地邁出了 CSS 學(xué)習(xí)的第一步。
“CSS 規(guī)則集”詳解
讓我們來仔細看一看上述CSS:
整個結(jié)構(gòu)稱為 規(guī)則集(通常簡稱“規(guī)則”),各部分釋義如下:
- 選擇器(Selector)
- HTML 元素的名稱位于規(guī)則集開始。它選擇了一個或者多個需要添加樣式的元素(在這個例子中就是 p 元素)。要給不同元素添加樣式只需要更改選擇器就行了。
- 聲明(Declaration)
- 一個單獨的規(guī)則,比如說 color: red; 用來指定添加樣式元素的屬性。
- 屬性(Properties)
- 改變 HTML 元素樣式的途徑。(本例中 color 就是 `` 元素的屬性。)CSS 中,由編寫人員決定修改哪個屬性以改變規(guī)則。
- 屬性的值(Property value)
- 在屬性的右邊,冒號后面即屬性的值,它從指定屬性的眾多外觀中選擇一個值(我們除了 red 之外還有很多屬性值可以用于 color )。
注意其他重要的語法:
- 每個規(guī)則集(除了選擇器的部分)都應(yīng)該包含在成對的大括號里({})。
- 在每個聲明里要用冒號(:)將屬性與屬性值分隔開。
- 在每個規(guī)則集里要用分號(;)將各個聲明分隔開。
如果要同時修改多個屬性,只需要將它們用分號隔開,就像這樣:
p {
color: red;
width: 500px;
border: 1px solid black;
}
多元素選擇
也可以選擇多種類型的元素并為它們添加一組相同的樣式。將不同的選擇器用逗號分開。例如:
p, li, h1 {
color: red;
}
不同類型的選擇器
選擇器有許多不同的類型。上面只介紹了元素選擇器,用來選擇 HTML 文檔中給定的元素。但是選擇的操作可以更加具體。下面是一些常用的選擇器類型:
選擇器名稱 | 選擇的內(nèi)容 | 示例 |
元素選擇器(也稱作標(biāo)簽或類型選擇器) | 所有指定(該)類型的 HTML 元素 | p 選擇 <p> |
ID 選擇器 | 具有特定 ID 的元素(單一 HTML 頁面中,每個 ID 只對應(yīng)一個元素,一個元素只對應(yīng)一個 ID) | #my-id 選擇 <p id="my-id"> 或 <a id="my-id"> |
類選擇器 | 具有特定類的元素(單一頁面中,一個類可以有多個實例) | .my-class 選擇 <p class="my-class"> 和 <a class="my-class"> |
屬性選擇器 | 擁有特定屬性的元素 | img[src] 選擇 <img src="myimage.png"> 而不是 <img> |
偽(Pseudo)類選擇器 | 特定狀態(tài)下的特定元素(比如鼠標(biāo)指針懸停) | a:hover 僅在鼠標(biāo)指針懸停在鏈接上時選擇 <a>。 |
選擇器的種類遠不止于此,更多信息請參閱 選擇器。
字體和文本
譯注:再一次說明,中文字體文件較大,不適合直接用于 Web Font。
在探索了一些 CSS 基礎(chǔ)后,我們來把更多規(guī)則和信息添加至 style.css 中,從而讓示例更美觀。首先,讓字體和文本變得更漂亮。
第一步:找到之前Google Font 輸出的地址。并以<link>元素的形式添加進index.html文檔頭(<head>和</head>之間的任意位置)。代碼如下:
<link href="https://fonts.font.im/css?family=Open+Sans" rel="stylesheet" type="text/css">
以上代碼為當(dāng)前網(wǎng)頁下載 Open Sans 字體,從而使自定義 CSS 中可以對 HTML 元素應(yīng)用這個字體。
第二步:接下來,刪除 style.css 文件中已有的規(guī)則。雖然測試是成功的了,但是紅字看起來并不太舒服。
第三步:將下列代碼添加到相應(yīng)的位置,用你在 Google Fonts 找到的字體替代 font-family 中的占位行。( font-family 意味著你想要你的文本使用的字體。)這條規(guī)則首先為整個頁面設(shè)定了一個全局字體和字號(因為 <html> 是整個頁面的父元素,而且它所有的子元素都會繼承相同的 font-size 和 font-family):
html {
/* px 表示 “像素(pixels)”: 基礎(chǔ)字號為 10 像素 */
font-size: 10px;
/* Google fonts 輸出的 CSS */
font-family: 'Open Sans', sans-serif;
}
注:CSS 文檔中所有位于 /* 和 */ 之間的內(nèi)容都是 CSS 注釋,它會被瀏覽器在渲染代碼時忽略。你可以在這里寫下對你現(xiàn)在要做的事情有幫助的筆記。
譯注:/*``*/ 不可嵌套,/*這樣的注釋是/*不行*/的*/。CSS 不接受 // 注釋。
接下來為文檔體內(nèi)的元素(<h1> (en-US)、<li>和<p>)設(shè)置字號。將標(biāo)題居中顯示,并為正文設(shè)置行高和字間距,從而提高頁面的可讀性。
h1 {
font-size: 60px;
text-align: center;
}
p, li {
font-size: 16px;
/* line-height 后而可以跟不同的參數(shù),如果是數(shù)字,就是當(dāng)前字體大小乘上數(shù)字 */
line-height: 2;
letter-spacing: 1px;
}
可以隨時調(diào)整這些 px 值來獲得滿意的結(jié)果,以下是大體效果:
一切皆盒子
編寫 CSS 時你會發(fā)現(xiàn),你的工作好像是圍繞著一個一個盒子展開的——設(shè)置尺寸、顏色、位置,等等。頁面里大部分 HTML 元素都可以被看作若干層疊的盒子。
并不意外,CSS 布局主要就是基于盒模型的。每個占據(jù)頁面空間的塊都有這樣的屬性:
- padding:即內(nèi)邊距,圍繞著內(nèi)容(比如段落)的空間。
- border:即邊框,緊接著內(nèi)邊距的線。
- margin:即外邊距,圍繞元素外部的空間。
這里還使用了:
- width :元素的寬度
- background-color :元素內(nèi)容和內(nèi)邊距底下的顏色
- color :元素內(nèi)容(通常是文本)的顏色
- text-shadow :為元素內(nèi)的文本設(shè)置陰影
- display :設(shè)置元素的顯示模式(暫略)
開始在頁面中添加更多 CSS 吧!大膽將這些新規(guī)則都添加到頁面的底部,而不要糾結(jié)改變屬性值會帶來什么結(jié)果。
更改頁面顏色
html{
background-color:#00539f;
}
這條規(guī)則將整個頁面的背景顏色設(shè)置為 所計劃的顏色。
文檔體格式設(shè)置
body{
width:600px;
margin:0 auto;
background-color:#ff9500;
padding:0 20px 20px 20px;
border:5px solid black;
}
現(xiàn)在是 <body> 元素。以上條聲明,我們來逐條查看:
- width: 600px; —— 強制頁面永遠保持 600 像素寬。
- margin: 0 auto; —— 為 margin 或 padding 等屬性設(shè)置兩個值時,第一個值代表元素的上方和下方(在這個例子中設(shè)置為 0),而第二個值代表左邊和右邊(在這里,auto 是一個特殊的值,意思是水平方向上左右對稱)。你也可以使用一個,三個或四個值,參考 這里 。
- background-color: #FF9500; —— 如前文所述,指定元素的背景顏色。我們給 body 用了一種略微偏紅的橘色以與深藍色的 `` 元素形成反差,你也可以嘗試其它顏色。
- padding: 0 20px 20px 20px; —— 我們給內(nèi)邊距設(shè)置了四個值來讓內(nèi)容四周產(chǎn)生一點空間。這一次我們不設(shè)置上方的內(nèi)邊距,設(shè)置右邊,下方,左邊的內(nèi)邊距為20像素。值以上、右、下、左的順序排列。
- border: 5px solid black; —— 直接為 body 設(shè)置 5 像素的黑色實線邊框。
定位頁面主標(biāo)題并添加樣式
h1{
margin: 0;
padding:20px 0;
color: #00539f;
text-shadow:3px 3px 1px black
}
你可能發(fā)現(xiàn)頁面的頂部有一個難看的間隙,那是因為瀏覽器會在沒有任何 CSS 的情況下 給 <h1>en-US等元素設(shè)置一些默認(rèn)樣式。但這并不是個好主意,因為我們希望一個沒有任何樣式的網(wǎng)頁也有基本的可讀性。為了去掉那個間隙,我們通過設(shè)置margin: 0;來覆蓋默認(rèn)樣式。
至此,我們已經(jīng)把標(biāo)題的上下內(nèi)邊距設(shè)置為 20 像素,并且將標(biāo)題文本與 HTML 的背景顏色設(shè)為一致。
需要注意的是,這里使用了一個 text-shadow 屬性,它可以為元素中的文本提供陰影。四個值含義如下:
- 第一個值設(shè)置水平偏移值 —— 即陰影右移的像素數(shù)(負值左移)。
- 第二個值設(shè)置垂直偏移值 —— 即陰影下移的像素數(shù)(負值上移)。
- 第三個值設(shè)置陰影的模糊半徑 —— 值越大產(chǎn)生的陰影越模糊。
- 第四個值設(shè)置陰影的基色。
不妨嘗試不同的值看看能得出什么結(jié)果。
圖像居中
img{
display:block;
margin:0 auto;
}
最后,我們把圖像居中來使頁面更美觀。可以復(fù)用 body 的margin: 0 auto,但是需要一點點調(diào)整。<body>元素是塊級元素,意味著它占據(jù)了頁面的空間并且能夠賦予外邊距和其他改變間距的值。而圖片是內(nèi)聯(lián)元素,不具備塊級元素的一些功能。所以為了使圖像有外邊距,我們必須使用display: block 給予其塊級行為。
注:以上說明假定所選圖片小于頁面寬度(600 pixels)。更大的圖片會溢出 body 并占據(jù)頁面的其他位置。要解決這個問題,可以:
1)使用 圖片編輯器 來減小圖片寬度; 2)用 CSS 限制圖片大小,即減小 <img> 元素 width 屬性的值(比如 400 px)。
注:如果你暫時不能理解 display: block 和塊級元素與行內(nèi)元素的差別也沒關(guān)系;隨著你對 CSS 學(xué)習(xí)的深入,你將明白這個問題。
小結(jié)
如果你按部就班完成本文的實踐,那么最終可以得到以下頁面
相關(guān)推薦:
前端新手看過來,手把手帶你輕松上手html的實操
我們向瀏覽器的地址欄輸入URL的時候,網(wǎng)絡(luò)會進行一系列的操作,最終獲取到我們所需要的文件,如何交給瀏覽器進行渲染
我們所關(guān)注的問題也就是:
大致的執(zhí)行順序
- URL解析
- DNS 解析:緩存判斷 + 查詢IP地址
- TCP 連接:TCP 三次握手
- SSL/TLS四次握手(只有https才有這一步)
- 瀏覽器發(fā)送請求
- 服務(wù)器響應(yīng)請求并返回數(shù)據(jù)
- 瀏覽器解析渲染頁面
- 斷開連接:TCP 四次揮手
URL解析
瀏覽器先會判斷輸入的字符是不是一個合法的URL結(jié)構(gòu),如果不是,瀏覽器會使用搜索引擎對這個字符串進行搜索
URL結(jié)構(gòu)組成
https://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#anchor
- 協(xié)議:https:// 互聯(lián)網(wǎng)支持多種協(xié)議,必須指明網(wǎng)址使用哪一種協(xié)議,默認(rèn)是 HTTP 協(xié)議。 也就是說,如果省略協(xié)議,直接在瀏覽器地址欄輸入www.example.com,那么瀏覽器默認(rèn)會訪問http://www.example.com。 HTTPS 是 HTTP 的加密版本,出于安全考慮,越來越多的網(wǎng)站使用這個協(xié)議。
- 主機:www.example.com 主機(host)是資源所在的網(wǎng)站名或服務(wù)器的名字,又稱為域名。上例的主機是www.example.com。 有些主機沒有域名,只有 IP 地址,比如192.168.2.15。
- 端口:https:// 同一個域名下面可能同時包含多個網(wǎng)站,它們之間通過端口(port)區(qū)分。 “端口”就是一個整數(shù),可以簡單理解成,訪問者告訴服務(wù)器,想要訪問哪一個網(wǎng)站。 默認(rèn)端口是80,如果省略了這個參數(shù),服務(wù)器就會返回80端口的網(wǎng)站。 端口緊跟在域名后面,兩者之間使用冒號分隔,比如www.example.com:80。
- 路徑:/path/to/myfile.html 路徑(path)是資源在網(wǎng)站的位置。比如,/path/index.html這個路徑,指向網(wǎng)站的/path子目錄下面的網(wǎng)頁文件index.html 互聯(lián)網(wǎng)的早期,路徑是真實存在的物理位置。現(xiàn)在由于服務(wù)器可以模擬這些位置,所以路徑只是虛擬位置 路徑可能只包含目錄,不包含文件名,比如/foo/,甚至結(jié)尾的斜杠都可以省略 這時,服務(wù)器通常會默認(rèn)跳轉(zhuǎn)到該目錄里面的index.html文件(即等同于請求/foo/index.html),但也可能有其他的處理(比如列出目錄里面的所有文件),這取決于服務(wù)器的設(shè)置 一般來說,訪問www.example.com這個網(wǎng)址,很可能返回的是網(wǎng)頁文件www.example.com/index.html
- 查詢參數(shù):?key1=value1&key2=value2 查詢參數(shù)(parameter)是提供給服務(wù)器的額外信息。參數(shù)的位置是在路徑后面,兩者之間使用?分隔 查詢參數(shù)可以有一組或多組。每組參數(shù)都是鍵值對(key-value pair)的形式,同時具有鍵名(key)和鍵值(value),它們之間使用等號(=)連接。比如,key1=value就是一個鍵值對,key1是鍵名,value1是鍵值 多組參數(shù)之間使用&連接,比如key1=value1&key2=value2
- 錨點:#anchor 錨點(anchor)是網(wǎng)頁內(nèi)部的定位點,使用#加上錨點名稱,放在網(wǎng)址的最后,比如#anchor 瀏覽器加載頁面以后,會自動滾動到錨點所在的位置 錨點名稱通過網(wǎng)頁元素的id屬性命名
DNS解析
DNS(Domain Names System),域名系統(tǒng),是互聯(lián)網(wǎng)一項服務(wù),是進行域名和與之相對應(yīng)的 IP 地址進行轉(zhuǎn)換的服務(wù)器
第一步:緩存判斷
判斷是正確的URL格式之后,DNS會在我們的緩存中查詢是否有當(dāng)前域名的IP地址
基本步驟:
- 瀏覽器緩存:瀏覽器檢查是否在緩存中
- 操作系統(tǒng)緩存:操作系統(tǒng)DNS緩存,去本地的hosts文件查找
- 路由器緩存:路由器DNS緩存
- ISP 緩存: ISP DNS緩存(ISP DNS 就是在客戶端電腦上設(shè)置的首選 DNS 服務(wù)器,又稱本地的DNS服務(wù)器)
在經(jīng)歷上述緩存查找還沒有找到的話,就進行下一步查詢操作
第二步:查詢IP地址
瀏覽器會去根域名服務(wù)器中查找,如果還沒有就去頂級域名服務(wù)器中查找,最后是權(quán)威域名服務(wù)器。
找到IP地址后,將它記錄在緩存中,供下次使用。
TCP連接:三次握手
簡單理解
簡單的理解就是:
客戶端:hello,你好,你是server嗎?
服務(wù)端:hello,你好,我是server,你是client嗎
客戶端:yes,我是client
開始數(shù)據(jù)傳輸.....
——————————————————————————————————————————
客戶端(男人):我喜歡你,咱倆處對象吧
服務(wù)端(女人):我也喜歡你,我答應(yīng)你
客戶端(男人):太棒了,我們現(xiàn)在去看電影吧
開始數(shù)據(jù)傳輸.....
然后雙方就正確建立連接,開始傳輸數(shù)據(jù)
詳細分析
- 第一次握手:客戶端發(fā)送一個帶 SYN=1,Seq=x 的數(shù)據(jù)包到服務(wù)器端口 第一次握手,由瀏覽器發(fā)起,告訴服務(wù)器我要發(fā)送請求了 SYN(synchronous):請求建立連接 seq(sequence):隨機序列號 請注意TCP規(guī)定SYN被設(shè)置為1的報文段不能攜帶數(shù)據(jù)但要消耗掉一個序號。
- 第二次握手:服務(wù)器發(fā)回一個帶 SYN=1, ACK=1, seq=y, ack=x+1 的響應(yīng)包以示傳達確認(rèn)信息 第二次握手,由服務(wù)器發(fā)起,告訴客戶端我準(zhǔn)備接受了,你趕緊發(fā)送吧 ACK(acknowledgement):確認(rèn),是一個確定字符 ack:ack=上一次的seq+1,作用是接受上一次遠端主機傳來的seq,加一然后再傳給客戶端,提示客戶端已經(jīng)成功接收上一次所有數(shù)據(jù) 請注意這個報文段不能攜帶數(shù)據(jù),因為它是SYN被設(shè)置為一的報文段但同樣要消耗掉一個序號
- 第三次握手:客戶端再回傳一個帶 ACK,seq=x + 1, ack=y + 1 的數(shù)據(jù)包,代表“握手結(jié)束” 第三次握手,由瀏覽器發(fā)送,告訴服務(wù)器,我馬上就發(fā)了,準(zhǔn)備接受吧 確認(rèn)報文段可以攜帶數(shù)據(jù)。但如果不攜帶數(shù)據(jù)則不消耗序號,在這種情況下所發(fā)送的下一個數(shù)據(jù)報文段的序號仍是x + 1
然后雙方就正確建立連接,開始傳輸數(shù)據(jù)
SSL/TLS四次握手
HTTPS 建立連接的過程,先進行 TCP 三次握手,再進行 TLS 四次握手(僅對https)
因為 HTTPS 都是基于 TCP 傳輸協(xié)議實現(xiàn)的,得先建立完可靠的 TCP 連接才能做 TLS 握手的事情。
第一次握手:客戶端發(fā)出請求Client Hello
- 首先,客戶端先向服務(wù)器發(fā)出加密通信的請求,這被叫做clienthello請求。
- 在這一步,客戶端主要向服務(wù)器提供以下信息:
- 支持的協(xié)議版本,比如TLS1.0版本
- 支持的加密方法,比如RSA公鑰加密
- 一個客戶端生成的隨機數(shù)(client random), 稍后用于生成對話密鑰(session key)
第二次握手:服務(wù)器回應(yīng)Server Hello
- 服務(wù)器收到客戶端請求后,向客戶端發(fā)出回應(yīng),這叫做serverhello
- 這一步服務(wù)器主要干三件事:
- 確認(rèn)使用的加密通信協(xié)議版本,比如TLS1.00版本。如果游覽器與服務(wù)器支持的版本不一致,服務(wù)器關(guān)閉加密通信
- 確認(rèn)使用的加密方法(客戶端所支持),比如RSA公鑰加密
- 將服務(wù)器證書、非對稱加密的公鑰,以及一個隨機數(shù)(Server random)發(fā)送給客戶端游覽器
客戶端驗證證書
客戶端收到服務(wù)器回應(yīng)以后,首先驗證服務(wù)器證書,驗證手段就是執(zhí)行如下三種檢查:
- 檢查證書是否已過期;
- 檢查證書中的域名與實際域名是否一致
- 檢查證書是否是可信機構(gòu)頒布的
如果,上述過程中有任何一個環(huán)節(jié)發(fā)現(xiàn)問題,那么瀏覽器就會向訪問者顯示一個警告,由其選擇是否還要繼續(xù)通信。如果證書受信任,或者是用戶接受了不受信的證書,瀏覽器會生成一串新的隨機數(shù)(Premaster secret )。
第三次握手:客戶端回應(yīng)
此時,瀏覽器會根據(jù)前三次握手中的三個隨機數(shù):
- Client random
- Server random
- Premaster secret
通過一定的算法來生成 “會話密鑰” (Session Key),這個會話密鑰就是接下來雙方進行對稱加密解密使用的密鑰!
第四次握手:服務(wù)端回應(yīng)
服務(wù)端收到客戶端的回復(fù),利用已知的加密解密方式進行解密,服務(wù)器收到客戶端的第三個隨機數(shù)( Premaster secret) 之后,使用同樣的算法計算出 “會話密鑰” (Session Key)。
至此,整個握手階段全部結(jié)束。接下來,客戶端與服務(wù)器進入加密通信,就完全是使用普通的 HTTP 協(xié)議,只不過用 “會話密鑰” 加密內(nèi)容。(非對稱加密解密將不再使用,接下來完全由對稱加密接手了,因為密鑰已經(jīng)安全的傳送給了通信的雙方)
總結(jié)
- 客戶端請求建立SSL鏈接,并向服務(wù)發(fā)送一個隨機數(shù)–Client random和客戶端支持的加密方法,比如RSA公鑰加密,此時是明文傳輸
- 服務(wù)端回復(fù)一種客戶端支持的加密方法、一個隨機數(shù)–Server random、授信的服務(wù)器證書和非對稱加密的公鑰
- 客戶端收到服務(wù)端的回復(fù)后利用服務(wù)端的公鑰,加上新的隨機數(shù)–Premaster secret 通過服務(wù)端下發(fā)的公鑰及加密方法進行加密,發(fā)送給服務(wù)器
- 服務(wù)端收到客戶端的回復(fù),利用已知的加解密方式進行解密,同時利用Client random、Server random和Premaster secret通過一定的算法生成HTTP鏈接數(shù)據(jù)傳輸?shù)膶ΨQ加密key – session key
瀏覽器發(fā)送請求
連接建立成功之后,瀏覽器向服務(wù)器發(fā)送HTTP請求報文,來獲取自己想要的數(shù)據(jù)
請求報文由請求行、請求頭、空行、請求體四部分組成
- 請求行:有請求方法、請求的url、http協(xié)議及其版本
- 請求頭:把瀏覽器的一些基礎(chǔ)信息告訴服務(wù)器。比如包含了瀏覽器所使用的操作系統(tǒng)、瀏覽器內(nèi)核等信息,以及當(dāng)前請求的域名信息、瀏覽器端的 Cookie 信息等
- 空行:最后一個請求頭之后是一個空行,發(fā)送回車符和換行符,通知服務(wù)器以下不再有請求頭
- 請求體(報文主體/請求中文):當(dāng)使用POST, PUT等方法時,通常需要客戶端向服務(wù)器傳遞數(shù)據(jù)。這些數(shù)據(jù)就儲存在請求正文中。在請求包頭中有一些與請求正文相關(guān)的信息,例如: 現(xiàn)在的Web應(yīng)用通常采用Rest架構(gòu),請求的數(shù)據(jù)格式一般為json。這時就需要設(shè)置Content-Type: application/json。
服務(wù)端響應(yīng)請求并返回數(shù)據(jù)
服務(wù)器對http請求報文進行解析,并給客戶端發(fā)送HTTP響應(yīng)報文對其進行響應(yīng)
HTTP響應(yīng)報文也是由狀態(tài)行、響應(yīng)頭、空行、響應(yīng)體四部分組成
- 響應(yīng)行/狀態(tài)行:由 HTTP 版本協(xié)議字段、狀態(tài)碼和狀態(tài)碼的描述文本 3 個部分組成
- 響應(yīng)頭:用于指示客戶端如何處理響應(yīng)體,告訴瀏覽器響應(yīng)的類型、字符編碼和字節(jié)大小等信息
- 空行:最后一個響應(yīng)頭部之后是一個空行,發(fā)送回車符和換行符,通知服務(wù)器以下不再有響應(yīng)頭部。
- 響應(yīng)體:返回客戶端所需數(shù)據(jù)
這個時候瀏覽器拿到我們服務(wù)器返回的HTML文件,可以開始解析渲染頁面
瀏覽器解析渲染頁面
當(dāng)我們經(jīng)歷了上述的一系列步驟之后,我們的瀏覽器就拿到了我的HTML文件那么它又是如何解析整個頁面并且最終呈現(xiàn)出我們的網(wǎng)頁呢?
渲染流程圖
簡圖:從這張圖上我們可以得出一個重要的結(jié)論:下載CSS文件并不會阻塞HTML的解析
詳圖:
詳細解析步驟
解析一:HTML解析過程
默認(rèn)情況下服務(wù)器會給瀏覽器返回index.html文件,所以解析HTML是所有步驟的開始:解析HTML,會 構(gòu)建DOM Tree
當(dāng)遇到我們的script文件的時候,我們是不能進行去構(gòu)建DOM Tree的。它會停止繼續(xù)構(gòu)建,首先下載JavaScript代碼,并且執(zhí)行JavaScript的腳本,只有等到JavaScript腳本執(zhí)行結(jié)束后,才會繼續(xù)解析HTML,構(gòu)建DOM樹。
具體的相關(guān)細節(jié)看下面的script與頁面解析
解析二:生成CSS規(guī)則
- 在解析的過程中,如果遇到CSS的link元素,那么會由瀏覽器負責(zé)下載對應(yīng)的CSS文件
- 瀏覽器下載完CSS文件后,就會對CSS文件進行解析,解析出對應(yīng)的規(guī)則樹
- 我們可以稱之為 CSSOM (CSS Object Model,CSS對象模型)
解析三:構(gòu)建Render Tree
當(dāng)有了 DOM Tree 和 CSSOM Tree 后,就可以兩個結(jié)合來 構(gòu)建 Render Tree
- 注意一:link元素不會阻塞DOM Tree的構(gòu)建過程,但是會阻塞Render Tree的構(gòu)建過程
- 因為Render Tree在構(gòu)建時,需要對應(yīng)的CSSOM Tree。當(dāng)我們DOMTree解析完成的時候,如果CSSOM Tree沒解析完成就會阻塞。當(dāng)然一般情況下瀏覽器會進行優(yōu)化處理,不會傻傻的等待
- 注意二:Render Tree和DOMTree并不是一一對應(yīng)的關(guān)系
- 比如對于display為none的元素,壓根不會出現(xiàn)在render tree中
解析四:布局(layout)和繪制(Paint)
- 第四步是在**渲染樹(Render Tree)**上運行 布局(Layout) 以計算每個節(jié)點的幾何體。 渲染樹會 表示 要顯示哪些節(jié)點以及其他樣式,但是 不表示 每個節(jié)點的尺寸、位置 等信息 布局的主要目的是為了確定呈現(xiàn)樹中所有節(jié)點的寬度、高度和位置信息
- 第五步是將每個節(jié)點 繪制(Paint) 到屏幕上 在繪制階段,瀏覽器將布局階段計算的 每個frame轉(zhuǎn)為屏幕上實際的像素點 包括 將元素的可見部分進行繪制,比如文本、顏色、邊框、陰影、替換元素(比如img)
特殊解析:composite合成
- 繪制的過程,可以將布局后的元素繪制到多個合成圖層中【這是瀏覽器的一種優(yōu)化手段】
- 默認(rèn)情況下,標(biāo)準(zhǔn)流中的內(nèi)容都是被繪制在同一個圖層(Layer)中的
- 而一些特殊的屬性,會創(chuàng)建一個新的合成層(Compositinglayer ),并且新的圖層可以利用GPU來加速繪制
- 那么哪些屬性可以形成新的合成層呢?常見的一些屬性:
- 3D transforms
- video、canvas、iframe
- opacity動畫轉(zhuǎn)換時
- position: fixed
- will-change:一個實驗性的屬性,提前告訴瀏覽器元素可能發(fā)生哪些變化
- animation或 transition設(shè)置了opacity、transform
- 分層確實可以提高性能,但是它以內(nèi)存管理為代價,因此不應(yīng)作為web性能優(yōu)化策略的一部分過度使用
其他相關(guān)概念
回流
- 回流reflow(也可以稱之為重排) 第一次確定節(jié)點的大小和位置,稱之為布局(layout) 之后對節(jié)點的大小、位置修改 重新計算 稱之為回流
- 什么情況下引起回流呢? 比如DOM結(jié)構(gòu)發(fā)生改變(添加新的節(jié)點或者移除節(jié)點) 比如改變了布局(修改了width、height、padding、font-size等值) 比如窗口resize(修改了窗口的尺寸等) 比如調(diào)用getComputedStyle方法獲取尺寸、位置信息
重繪
- 重繪repaint【字面理解就是對頁面再做繪制】 第一次渲染內(nèi)容稱之為繪制(paint) 之后重新渲染稱之為重繪
- 什么情況下會引起重繪呢? 比如修改背景色、文字顏色、邊框顏色、樣式等
聯(lián)系
- 回流一定會引起重繪,所以回流是一件很消耗性能的事情。
- 所以在開發(fā)中要盡量避免發(fā)生回流 修改樣式時盡量一次性修改【比如通過cssText修改,比如通過添加class修改】 盡量 避免頻繁的操作DOM【我們可以在一個DocumentFragment或者父元素中將要操作的DOM操作完成,再一次性的操作】 盡量 避免通過getComputedStyle獲取尺寸、位置等信息 對某些元素使用position的absolute或者fixed【并不是不會引起回流,而是開銷相對較小,不會對其他元素造成影響】
script元素
script元素和頁面聯(lián)系
- 我們現(xiàn)在已經(jīng)知道了頁面的渲染過程,但是JavaScript在哪里呢? 事實上,瀏覽器在解析HTML的過程中,遇到了 script元素是不能繼續(xù)構(gòu)建DOM樹的 它會 停止繼續(xù)構(gòu)建,首先下載JavaScript代碼,并且執(zhí)行JavaScript的腳本 只有 等到JavaScript腳本執(zhí)行結(jié)束后,才會繼續(xù)解析HTML,構(gòu)建DOM樹
- 為什么要這樣做呢? 這是 因為JavaScript的作用之一就是操作DOM,并且可以修改DOM 如果我們等到DOM樹構(gòu)建完成并且渲染再執(zhí)行JavaScript會造成嚴(yán)重的回流和重繪,影響頁面的性能 所以會在遇到script元素時,優(yōu)先下載和執(zhí)行JavaScript代碼,再繼續(xù)構(gòu)建DOM樹
- 但是這個也往往會帶來新的問題,特別是現(xiàn)代頁面開發(fā)中: 在目前的開發(fā)模式中(比如Vue、React),腳本往往比HTML頁面更“重”,處理時間需要更長 所以會造成頁面的解析阻塞,在腳本下載、執(zhí)行完成之前,用戶在界面上什么都看不到
- 為了解決這個問題,script元素給我們提供了兩個屬性(attribute) : defer和async
defer屬性
- defer屬性告訴瀏覽器 不要等待腳本下載,而繼續(xù)解析HTML,構(gòu)建DOM Tree
- 腳本會 由瀏覽器來進行下載,但是不會阻塞DOM Tree的構(gòu)建過程
- 如果腳本提前下載好了,它會 等待DOM Tree構(gòu)建完成,在DOMContentLoaded事件之前先執(zhí)行defer中的代碼
- 所以DOMContentLoaded總是會等待defer中的代碼先執(zhí)行完成
<script src="./foo.js" defer></script>
<script>
window.addEventListener("DOMContentLoaded",()=>{
console.log("DOMContentLoaded");
})
</script>
- 多個帶defer的腳步是可以保持正確的執(zhí)行順序的
- 從某種角度來說,defer可以提高頁面的性能,并且推薦放到head元素中
- 注意:defer僅適用于外部腳本,對于script默認(rèn)內(nèi)容會被忽略
async屬性
- async特性與defer有些類似,它也能夠讓腳本不阻塞頁面
- async是讓一個腳本完全獨立的:
- 瀏覽器 不會因async 腳本而阻塞(與defer類似)
- async腳本不能保證順序,它是獨立下載、獨立運行,不會等待其他腳本
- async不會能保證在DOMContentLoaded之前或者之后執(zhí)行
- defer通常用于需要在文檔解析后操作DOM的JavaScript代碼,并且對多個script文件有順序要求的
- async通常用于獨立的腳本,對其他腳本,甚至DOM沒有依賴的
斷開連接:TCP 四次揮手
在渲染完成后,瀏覽器可能會繼續(xù)加載頁面中的其他資源,如異步加載的內(nèi)容或者通過JavaScript生成的動態(tài)內(nèi)容。
而在此過程中,如果沒有其他資源需要加載,瀏覽器將與服務(wù)器之間的TCP連接斷開。
簡單理解
復(fù)制代碼主動方:我已經(jīng)關(guān)閉了向你那邊的主動通道了,這是我最后一次給你發(fā)消息了,之后只能被動接收你的信息了
被動方:收到你通道關(guān)閉的信息
被動方:那我也告訴你,我這邊向你的主動通道也關(guān)閉了
主動方:最后收到你關(guān)閉的信息,OK結(jié)束
斷開連接,結(jié)束通訊
————————————————————————————————————————————————————————————————————————————
提出分手的可能是男生(客戶端),也可能是女生(服務(wù)端)
主動方:分手吧,我不喜歡你了!
被動方:行,你等我忙完手上的工作我在收拾你!
被動方:我忙完了,分手就分手!
主動方:好,好聚好散,拜拜!
斷開連接,結(jié)束通訊
詳細分析
由于TCP連接是全雙工的,因此,每個方向都必須要單獨進行關(guān)閉,這一原則是當(dāng)一方完成數(shù)據(jù)發(fā)送任務(wù)后,發(fā)送一個FIN來終止這一方向的連接,收到一個FIN只是意味著這一方向上沒有數(shù)據(jù)流動了,即不會再收到數(shù)據(jù)了,但是在這個TCP連接上仍然能夠發(fā)送數(shù)據(jù),直到這一方向也發(fā)送了FIN。首先進行關(guān)閉的一方將執(zhí)行主動關(guān)閉,而另一方則執(zhí)行被動關(guān)閉。
任何一方都可以在數(shù)據(jù)傳送結(jié)束后發(fā)出連接釋放的通知,所有主動發(fā)起關(guān)閉請求可以是客戶端,也可以是服務(wù)端
這里我們假設(shè)是由客戶端先主動發(fā)起關(guān)閉請求
- 第一次揮手:TCP客戶進程會發(fā)送TCP連接釋放報文段,并進入終止等待1(FIN-WAIT-1)狀態(tài)。 FIN:終止位,表示斷開TCP連接 TCP規(guī)定終止位FIN等于1的報文段即使不攜帶數(shù)據(jù),也要消耗掉一個序號
- 第二次揮手:TCP服務(wù)器進程收到TCP連接釋放報文段后,會發(fā)送一個普通的TCP確認(rèn)報文段并進入關(guān)閉等待(CLOSE-WAIT)狀態(tài)。 序號seq字段的值設(shè)置為v,與之前收到的TCP連接釋放報文段中的確認(rèn)號匹配 TCP客戶進程收到TCP確認(rèn)報文段后就進入終止等待2(FIN-WAIT-2)狀態(tài),等待TCP服務(wù)器進程發(fā)出的TCP連接釋放報文段 這時的TCP連接屬于半關(guān)閉狀態(tài),也就是TCP客戶進程已經(jīng)沒有數(shù)據(jù)要發(fā)送了。但如果TCP服務(wù)器進程還有數(shù)據(jù)要發(fā)送,TCP客戶進程仍要接收,也就是說從TCP服務(wù)器進程到TCP客戶進程這個方向的連接并未關(guān)閉,這個狀態(tài)可能要持續(xù)一段時間。
- 第三次揮手:TCP服務(wù)器進程發(fā)送TCP連接釋放報文段 假定序號seq字段的值為w,這是因為在半關(guān)閉狀態(tài)下,TCP服務(wù)器進程可能又發(fā)送了一些數(shù)據(jù)。 確認(rèn)號ack字段的值為u+1,這是對之前收到的TCP連接釋放報文段的重復(fù)確認(rèn)。
- 第四次揮手:TCP服務(wù)器進程收到確定報文段后就進入關(guān)閉狀態(tài),而TCP客戶進程還要經(jīng)過2MSL后才能進入關(guān)閉狀態(tài)。
之后斷開連接,結(jié)束通訊
總結(jié)
- 瀏覽器先判斷是否為合法的url格式,不合法則在搜索引擎中搜索
- 合法后,DNS解析會先判斷緩存中是否有url的ip地址。
- 緩存的查詢順序是:瀏覽器緩存 -> 操作系統(tǒng)緩存(本地的hosts文件) -> 路由器緩存 -> 本地的DNS服務(wù)器緩存
- 在緩存中沒有的情況,則向服務(wù)器發(fā)起請求查詢ip地址。
- 查詢IP地址的順序是:根域名服務(wù)器 -> 頂級域名服務(wù)器 -> 權(quán)威域名服務(wù)器。直到查找到返回,并將其存儲在緩存中下次使用
- 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四次握手
- 第一次握手,客戶端向服務(wù)端發(fā)送 支持的協(xié)議版本 + 支持的加密方法 + 生成的隨機數(shù)
- 第二次握手,服務(wù)端向客戶端發(fā)送 證書 + 公鑰 + 隨機數(shù)
- 第三次握手前,客戶端會先驗證證書有沒有過期、域名對不對、是否可信機構(gòu)頒發(fā)的。
- 沒有問題或者用戶接受不受信的證書,瀏覽器會生成一個新的隨機數(shù)
- 第三次握手,將之前的三個隨機數(shù)通過一定的算法生成會話秘鑰,之后的加密解密都是用這個秘鑰
- 第四次握手,服務(wù)端收到回復(fù),是用確定的加密方法進行解密,得到第三個隨機數(shù),使用同樣的算法計算出會話秘鑰
- 建立連接之后,瀏覽器發(fā)送http請求
- 請求報文由請求行、請求頭、空行和請求體組成
- 服務(wù)器解析請求報文,返回響應(yīng)報文
- 響應(yīng)報文由響應(yīng)行、響應(yīng)頭、空行和響應(yīng)體組成,我們需要的html文件就在響應(yīng)體中
- 瀏覽器拿到html文件并開始解析,構(gòu)建dom tree。遇到css文件,下載并構(gòu)建CSSOM tree。等到兩者都構(gòu)建完成之后,一起構(gòu)建Render tree。然后進行布局和繪制
- 其中遇到了script標(biāo)簽,則停止構(gòu)建dom tree,等下載完成之后才會繼續(xù)構(gòu)建dom tree
- 當(dāng)資源傳輸完畢之后,TSP關(guān)閉連接,進行四次揮手的操作,其中四次揮手的操作客戶端和服務(wù)器都可以發(fā)起
- 第一次揮手,攜帶斷開連接的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后進入關(guān)閉狀態(tài)
- 斷開連接,結(jié)束通訊
作者:前端實習(xí)生鯨落
鏈接:https://juejin.cn/post/7279093851000242234