整合營(yíng)銷(xiāo)服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢(xún)熱線(xiàn):

          從你輸入一個(gè)網(wǎng)址,到網(wǎng)頁(yè)顯示,其間發(fā)生了什么?

          從你輸入一個(gè)網(wǎng)址,到網(wǎng)頁(yè)顯示,其間發(fā)生了什么?

          下文章來(lái)源于小林coding ,作者小林coding

          想必不少小伙伴面試過(guò)程中,會(huì)遇到「當(dāng)鍵入網(wǎng)址后,到網(wǎng)頁(yè)顯示,其間發(fā)生了什么」的面試題。

          這次,小林我?guī)Т蠹乙黄鹛骄肯拢粋€(gè)數(shù)據(jù)包在網(wǎng)絡(luò)中的心路歷程。

          每個(gè)階段都有數(shù)據(jù)包的「心路歷程」,我們一起看看它說(shuō)了什么?

          正文

          接下來(lái)以下圖較簡(jiǎn)單的網(wǎng)絡(luò)拓?fù)淠P妥鳛槔樱骄刻骄科溟g發(fā)生了什么?

          簡(jiǎn)單的網(wǎng)絡(luò)模型

          01 孤單小弟 —— HTTP

          瀏覽器做的第一步工作是解析 URL

          首先瀏覽器做的第一步工作就是要對(duì) URL 進(jìn)行解析,從而生發(fā)送給 Web 服務(wù)器的請(qǐng)求信息。

          讓我們看看一條長(zhǎng)長(zhǎng)的 URL 里的各個(gè)元素的代表什么,見(jiàn)下圖:

          URL 解析

          所以圖中的長(zhǎng)長(zhǎng)的 URL 實(shí)際上是請(qǐng)求服務(wù)器里的文件資源。

          要是上圖中的藍(lán)色部分 URL 元素都省略了,哪應(yīng)該是請(qǐng)求哪個(gè)文件呢?

          當(dāng)沒(méi)有路徑名時(shí),就代表訪問(wèn)根目錄下事先設(shè)置的默認(rèn)文件,也就是 /index.html 或者 /default.html 這些文件,這樣就不會(huì)發(fā)生混亂了。

          生產(chǎn) HTTP 請(qǐng)求信息

          對(duì) URL 進(jìn)行解析之后,瀏覽器確定了 Web 服務(wù)器和文件名,接下來(lái)就是根據(jù)這些信息來(lái)生成 HTTP 請(qǐng)求消息了。

          HTTP 的消息格式

          一個(gè)孤單 HTTP 數(shù)據(jù)包表示:“我這么一個(gè)小小的數(shù)據(jù)包,沒(méi)親沒(méi)友,直接發(fā)到浩瀚的網(wǎng)絡(luò),誰(shuí)會(huì)知道我呢?誰(shuí)能載我一層呢?誰(shuí)能保護(hù)我呢?我的目的地在哪呢?”。充滿(mǎn)各種疑問(wèn)的它,沒(méi)有停滯不前,依然踏上了征途!

          02 真實(shí)地址查詢(xún) —— DNS

          通過(guò)瀏覽器解析 URL 并生成 HTTP 消息后,需要委托操作系統(tǒng)將消息發(fā)送給 Web 服務(wù)器。

          但在發(fā)送之前,還有一項(xiàng)工作需要完成,那就是查詢(xún)服務(wù)器域名對(duì)于的 IP 地址,因?yàn)槲胁僮飨到y(tǒng)發(fā)送消息時(shí),必須提供通信對(duì)象的 IP 地址。

          比如我們打電話(huà)的時(shí)候,必須要知道對(duì)方的電話(huà)號(hào)碼,但由于電話(huà)號(hào)碼難以記憶,所以通常我們會(huì)將對(duì)方電話(huà)號(hào) + 姓名保存在通訊錄里。

          所以,有一種服務(wù)器就專(zhuān)門(mén)保存了 Web 服務(wù)器域名與 IP 的對(duì)應(yīng)關(guān)系,它就是 DNS 服務(wù)器。

          域名的層級(jí)關(guān)系

          DNS 中的域名都是用句點(diǎn)來(lái)分隔的,比如 www.server.com,這里的句點(diǎn)代表了不同層次之間的界限。

          在域名中,越靠右的位置表示其層級(jí)越高。

          畢竟域名是外國(guó)人發(fā)明,所以思維和中國(guó)人相反,比如說(shuō)一個(gè)城市地點(diǎn)的時(shí)候,外國(guó)喜歡從小到大的方式順序說(shuō)起(如 XX 街道 XX 區(qū) XX 市 XX 省),而中國(guó)則喜歡從大到小的順序(如 XX 省 XX 市 XX 區(qū) XX 街道)。

          根域是在最頂層,它的下一層就是 com 頂級(jí)域,再下面是 server.com。

          所以域名的層級(jí)關(guān)系類(lèi)似一個(gè)樹(shù)狀結(jié)構(gòu):

          • 根 DNS 服務(wù)器
          • 頂級(jí)域 DNS 服務(wù)器(com)
          • 權(quán)威 DNS 服務(wù)器(server.com)

          DNS 樹(shù)狀結(jié)構(gòu)

          根域的 DNS 服務(wù)器信息保存在互聯(lián)網(wǎng)中所有的 DNS 服務(wù)器中。

          這樣一來(lái),任何 DNS 服務(wù)器就都可以找到并訪問(wèn)根域 DNS 服務(wù)器了。

          因此,客戶(hù)端只要能夠找到任意一臺(tái) DNS 服務(wù)器,就可以通過(guò)它找到根域 DNS 服務(wù)器,然后再一路順藤摸瓜找到位于下層的某臺(tái)目標(biāo) DNS 服務(wù)器。

          域名解析的工作流程

          1. 客戶(hù)端首先會(huì)發(fā)出一個(gè) DNS 請(qǐng)求,問(wèn) www.server.com 的 IP 是啥,并發(fā)給本地 DNS 服務(wù)器(也就是客戶(hù)端的 TCP/IP 設(shè)置中填寫(xiě)的 DNS 服務(wù)器地址)。
          2. 本地域名服務(wù)器收到客戶(hù)端的請(qǐng)求后,如果緩存里的表格能找到 www.server.com,則它直接返回 IP 地址。如果沒(méi)有,本地 DNS 會(huì)去問(wèn)它的根域名服務(wù)器:“老大, 能告訴我 www.cxyxiaowu.com 的 IP 地址嗎?” 根域名服務(wù)器是最高層次的,它不直接用于域名解析,但能指明一條道路。
          3. 根 DNS 收到來(lái)自本地 DNS 的請(qǐng)求后,發(fā)現(xiàn)后置是 .com,說(shuō):“www.server.com 這個(gè)域名歸 .com 區(qū)域管理”,我給你 .com 頂級(jí)域名服務(wù)器地址給你,你去問(wèn)問(wèn)它吧。”
          4. 本地 DNS 收到頂級(jí)域名服務(wù)器的地址后,發(fā)起請(qǐng)求問(wèn)“老二, 你能告訴我 www.server.com 的 IP 地址嗎?”
          5. 頂級(jí)域名服務(wù)器說(shuō):“我給你負(fù)責(zé) www.server.com 區(qū)域的權(quán)威 DNS 服務(wù)器的地址,你去問(wèn)它應(yīng)該能問(wèn)到”。
          6. 本地 DNS 于是轉(zhuǎn)向問(wèn)權(quán)威 DNS 服務(wù)器:“老三,www.server.com對(duì)應(yīng)的IP是啥呀?” server.com 的權(quán)威 DNS 服務(wù)器,它是域名解析結(jié)果的原出處。為啥叫權(quán)威呢?就是我的域名我做主。
          7. 權(quán)威 DNS 服務(wù)器查詢(xún)后將對(duì)應(yīng)的 IP 地址 X.X.X.X 告訴本地 DNS。
          8. 本地 DNS 再將 IP 地址返回客戶(hù)端,客戶(hù)端和目標(biāo)建立連接。

          至此,我們完成了 DNS 的解析過(guò)程。現(xiàn)在總結(jié)一下,整個(gè)過(guò)程我畫(huà)成了一個(gè)圖。

          域名解析的工作流程

          DNS 域名解析的過(guò)程蠻有意思的,整個(gè)過(guò)程就和我們?nèi)粘I钪姓胰藛?wèn)路的過(guò)程類(lèi)似,只指路不帶路。

          數(shù)據(jù)包表示:“DNS 老大哥厲害呀,找到了目的地了!我還是很迷茫呀,我要發(fā)出去,接下來(lái)我需要誰(shuí)的幫助呢?”

          03 指南好幫手 —— 協(xié)議棧

          通過(guò) DNS 獲取到 IP 后,就可以把 HTTP 的傳輸工作交給操作系統(tǒng)中的協(xié)議棧。

          協(xié)議棧的內(nèi)部分為幾個(gè)部分,分別承擔(dān)不同的工作。上下關(guān)系是有一定的規(guī)則的,上面的部分會(huì)向下面的部分委托工作,下面的部分收到委托的工作并執(zhí)行。

          應(yīng)用程序(瀏覽器)通過(guò)調(diào)用 Socket 庫(kù),來(lái)委托協(xié)議棧工作。協(xié)議棧的上半部分有兩塊,分別是負(fù)責(zé)收發(fā)數(shù)據(jù)的 TCP 和 UDP 協(xié)議,它們兩會(huì)接受應(yīng)用層的委托執(zhí)行收發(fā)數(shù)據(jù)的操作。

          協(xié)議棧的下面一半是用 IP 協(xié)議控制網(wǎng)絡(luò)包收發(fā)操作,在互聯(lián)網(wǎng)上傳數(shù)據(jù)時(shí),數(shù)據(jù)劊被切分成一塊塊的網(wǎng)絡(luò)包,而將網(wǎng)絡(luò)包發(fā)送給對(duì)方的操作就是由 IP 負(fù)責(zé)的。

          此外 IP 中還包括 ICMP 協(xié)議和 ARP 協(xié)議。

          • ICMP 用于告知網(wǎng)絡(luò)包傳送過(guò)程中產(chǎn)生的錯(cuò)誤以及各種控制信息。
          • ARP 用于根據(jù) IP 地址查詢(xún)相應(yīng)的以太網(wǎng) MAC 地址。

          IP 下面的網(wǎng)卡驅(qū)動(dòng)程序負(fù)責(zé)控制網(wǎng)卡硬件,而最下面的網(wǎng)卡則負(fù)責(zé)完成實(shí)際的收發(fā)操作,也就是對(duì)網(wǎng)線(xiàn)中的信號(hào)執(zhí)行發(fā)送和接收操作。

          數(shù)據(jù)包看了這份指南表示:“原來(lái)我需要那么多大佬的協(xié)助啊,那我先去找找 TCP 大佬!”

          04 可靠傳輸 —— TCP

          HTTP 是基于 TCP 協(xié)議傳輸?shù)模栽谶@我們先了解下 TCP 協(xié)議。

          TCP 包頭格式

          我們先看看 TCP 報(bào)文頭部的格式:

          TCP 包頭格式

          首先,源端口號(hào)和目標(biāo)端口號(hào)是不可少的,如果沒(méi)有這兩個(gè)端口號(hào),數(shù)據(jù)就不知道應(yīng)該發(fā)給哪個(gè)應(yīng)用。

          接下來(lái)有包的序號(hào),這個(gè)是為了解決包亂序的問(wèn)題。

          還有應(yīng)該有的是確認(rèn)號(hào),目的是確認(rèn)發(fā)出去對(duì)方是否有收到。如果沒(méi)有收到就應(yīng)該重新發(fā)送,直到送達(dá),這個(gè)是為了解決不丟包的問(wèn)題。

          接下來(lái)還有一些狀態(tài)位。例如 SYN 是發(fā)起一個(gè)連接,ACK 是回復(fù),RST 是重新連接,F(xiàn)IN 是結(jié)束連接等。TCP 是面向連接的,因而雙方要維護(hù)連接的狀態(tài),這些帶狀態(tài)位的包的發(fā)送,會(huì)引起雙方的狀態(tài)變更。

          還有一個(gè)重要的就是窗口大小。TCP 要做流量控制,通信雙方各聲明一個(gè)窗口(緩存大小),標(biāo)識(shí)自己當(dāng)前能夠的處理能力,別發(fā)送的太快,撐死我,也別發(fā)的太慢,餓死我。

          除了做流量控制以外,TCP還會(huì)做擁塞控制,對(duì)于真正的通路堵車(chē)不堵車(chē),它無(wú)能為力,唯一能做的就是控制自己,也即控制發(fā)送的速度。不能改變世界,就改變自己嘛。

          TCP 傳輸數(shù)據(jù)之前,要先三次握手建立連接

          在 HTTP 傳輸數(shù)據(jù)之前,首先需要 TCP 建立連接,TCP 連接的建立,通常稱(chēng)為三次握手。

          這個(gè)所謂的「連接」,只是雙方計(jì)算機(jī)里維護(hù)一個(gè)狀態(tài)機(jī),在連接建立的過(guò)程中,雙方的狀態(tài)變化時(shí)序圖就像這樣。

          TCP 三次握手

          • 一開(kāi)始,客戶(hù)端和服務(wù)端都處于 CLOSED 狀態(tài)。先是服務(wù)端主動(dòng)監(jiān)聽(tīng)某個(gè)端口,處于 LISTEN 狀態(tài)。
          • 然后客戶(hù)端主動(dòng)發(fā)起連接 SYN,之后處于 SYN-SENT 狀態(tài)。
          • 服務(wù)端收到發(fā)起的連接,返回 SYN,并且 ACK 客戶(hù)端的 SYN,之后處于 SYN-RCVD 狀態(tài)。
          • 客戶(hù)端收到服務(wù)端發(fā)送的 SYN 和 ACK 之后,發(fā)送 ACK 的 ACK,之后處于 ESTABLISHED 狀態(tài),因?yàn)樗话l(fā)一收成功了。
          • 服務(wù)端收到 ACK 的 ACK 之后,處于 ESTABLISHED 狀態(tài),因?yàn)樗惨话l(fā)一收了。

          所以三次握手目的是保證雙方都有發(fā)送和接收的能力。

          如何查看 TCP 的連接狀態(tài)?

          TCP 的連接狀態(tài)查看,在 Linux 可以通過(guò) netstat -napt 命令查看。

          TCP 連接狀態(tài)查看

          TCP 分割數(shù)據(jù)

          如果 HTTP 請(qǐng)求消息比較長(zhǎng),超過(guò)了 MSS 的長(zhǎng)度,這時(shí) TCP 就需要把 HTTP 的數(shù)據(jù)拆解一塊塊的數(shù)據(jù)發(fā)送,而不是一次性發(fā)送所有數(shù)據(jù)。

          MTU 與 MSS

          • MTU:一個(gè)網(wǎng)絡(luò)包的最大長(zhǎng)度,以太網(wǎng)中一般為 1500 字節(jié)。
          • MSS:除去 IP 和 TCP 頭部之后,一個(gè)網(wǎng)絡(luò)包所能容納的 TCP 數(shù)據(jù)的最大長(zhǎng)度。

          數(shù)據(jù)會(huì)被以 MSS 的長(zhǎng)度為單位進(jìn)行拆分,拆分出來(lái)的每一塊數(shù)據(jù)都會(huì)被放進(jìn)單獨(dú)的網(wǎng)絡(luò)包中。也就是在每個(gè)被拆分的數(shù)據(jù)加上 TCP 頭信息,然后交給 IP 模塊來(lái)發(fā)送數(shù)據(jù)。

          數(shù)據(jù)包分割

          TCP 報(bào)文生成

          TCP 協(xié)議里面會(huì)有兩個(gè)端口,一個(gè)是瀏覽器監(jiān)聽(tīng)的端口(通常是隨機(jī)生成的),一個(gè)是 Web 服務(wù)器監(jiān)聽(tīng)的端口(HTTP 默認(rèn)端口號(hào)是 80, HTTPS 默認(rèn)端口號(hào)是 443)。

          在雙方建立了連接后,TCP 報(bào)文中的數(shù)據(jù)部分就是存放 HTTP 頭部 + 數(shù)據(jù),組裝好 TCP 報(bào)文之后,就需交給下面的網(wǎng)絡(luò)層處理。

          至此,網(wǎng)絡(luò)包的報(bào)文如下圖。

          TCP 層報(bào)文

          此時(shí),遇上了 TCP 的 數(shù)據(jù)包激動(dòng)表示:“太好了,碰到了可靠傳輸?shù)?TCP 傳輸,它給我加上 TCP 頭部,我不在孤單了,安全感十足啊!有大佬可以保護(hù)我的可靠送達(dá)!但我應(yīng)該往哪走呢?”

          05 遠(yuǎn)程定位 —— IP

          TCP 模塊在執(zhí)行連接、收發(fā)、斷開(kāi)等各階段操作時(shí),都需要委托 IP 模塊將數(shù)據(jù)封裝成網(wǎng)絡(luò)包發(fā)送給通信對(duì)象。

          IP 包頭格式

          我們先看看 IP 報(bào)文頭部的格式:

          IP 包頭格式

          在 IP 協(xié)議里面需要有源地址 IP 和 目標(biāo)地址 IP:

          • 源地址IP,即是客戶(hù)端輸出的 IP 地址;
          • 目標(biāo)地址,即通過(guò) DNS 域名解析得到的 Web 服務(wù)器 IP。

          因?yàn)?HTTP 是經(jīng)過(guò) TCP 傳輸?shù)模栽?IP 包頭的協(xié)議號(hào),要填寫(xiě)為 06(十六進(jìn)制),表示協(xié)議為 TCP。

          假設(shè)客戶(hù)端有多個(gè)網(wǎng)卡,就會(huì)有多個(gè) IP 地址,那 IP 頭部的源地址應(yīng)該選擇哪個(gè) IP 呢?

          當(dāng)存在多個(gè)網(wǎng)卡時(shí),在填寫(xiě)源地址 IP 時(shí),就需要判斷到底應(yīng)該填寫(xiě)哪個(gè)地址。這個(gè)判斷相當(dāng)于在多塊網(wǎng)卡中判斷應(yīng)該使用哪個(gè)一塊網(wǎng)卡來(lái)發(fā)送包。

          這個(gè)時(shí)候就需要根據(jù)路由表規(guī)則,來(lái)判斷哪一個(gè)網(wǎng)卡作為源地址 IP。

          在 Linux 操作系統(tǒng),我們可以使用 route -n 命令查看當(dāng)前系統(tǒng)的路由表。

          路由表

          舉個(gè)例子,根據(jù)上面的路由表,我們假設(shè) Web 服務(wù)器的目標(biāo)地址是 192.168.10.200。

          路由規(guī)則判斷

          1. 首先先和第一條條目的子網(wǎng)掩碼(Genmask)進(jìn)行 與運(yùn)算,得到結(jié)果為 192.168.10.0,但是第一個(gè)條目的 Destination 是 192.168.3.0,兩者不一致所以匹配失敗。
          2. 再與第二條目的子網(wǎng)掩碼進(jìn)行 與運(yùn)算,得到的結(jié)果為 192.168.10.0,與第二條目的 Destination 192.168.10.0 匹配成功,所以將使用 eth1 網(wǎng)卡的 IP 地址作為 IP 包頭的源地址。

          那么假設(shè) Web 服務(wù)器的目標(biāo)地址是 10.100.20.100,那么依然依照上面的路由表規(guī)則判斷,判斷后的結(jié)果是和第三條目匹配。

          第三條目比較特殊,它目標(biāo)地址和子網(wǎng)掩碼都是 0.0.0.0,這表示默認(rèn)網(wǎng)關(guān),如果其他所有條目都無(wú)法匹配,就會(huì)自動(dòng)匹配這一行。并且后續(xù)就把包發(fā)給路由器,Gateway 即是路由器的 IP 地址。

          IP 報(bào)文生成

          至此,網(wǎng)絡(luò)包的報(bào)文如下圖。

          IP 層報(bào)文

          此時(shí),加上了 IP 頭部的數(shù)據(jù)包表示 :“有 IP 大佬給我指路了,感謝 IP 層給我加上了 IP 包頭,讓我有了遠(yuǎn)程定位的能力!不會(huì)害怕在浩瀚的互聯(lián)網(wǎng)迷茫了!可是目的地好遠(yuǎn)啊,我下一站應(yīng)該去哪呢?”

          06 兩點(diǎn)傳輸 —— MAC

          生成了 IP 頭部之后,接下來(lái)網(wǎng)絡(luò)包還需要在 IP 頭部的前面加上 MAC 頭部。

          MAC 包頭格式

          MAC 頭部是以太網(wǎng)使用的頭部,它包含了接收方和發(fā)送方的 MAC 地址等信息。

          MAC 包頭格式

          在 MAC 包頭里需要發(fā)送方 MAC 地址和接收方目標(biāo) MAC 地址,用于兩點(diǎn)之間的傳輸。

          一般在 TCP/IP 通信里,MAC 包頭的協(xié)議類(lèi)型只使用:

          • 0800 :IP 協(xié)議
          • 0806 :ARP 協(xié)議

          MAC 發(fā)送方和接收方如何確認(rèn)?

          發(fā)送方的 MAC 地址獲取就比較簡(jiǎn)單了,MAC 地址是在網(wǎng)卡生產(chǎn)時(shí)寫(xiě)入到 ROM 里的,只要將這個(gè)值讀取出來(lái)寫(xiě)入到 MAC 頭部就可以了。

          接收方的 MAC 地址就有點(diǎn)復(fù)雜了,只要告訴以太網(wǎng)對(duì)方的 MAC 的地址,以太網(wǎng)就會(huì)幫我們把包發(fā)送過(guò)去,那么很顯然這里應(yīng)該填寫(xiě)對(duì)方的 MAC 地址。

          所以先得搞清楚應(yīng)該把包發(fā)給誰(shuí),這個(gè)只要查一下路由表就知道了。在路由表中找到相匹配的條目,然后把包發(fā)給 Gateway 列中的 IP 地址就可以了。

          既然知道要發(fā)給誰(shuí),按如何獲取對(duì)方的 MAC 地址呢?

          不知道對(duì)方 MAC 地址?不知道就喊唄。

          此時(shí)就需要 ARP 協(xié)議幫我們找到路由器的 MAC 地址。

          ARP 廣播

          ARP 協(xié)議會(huì)在以太網(wǎng)中以廣播的形式,對(duì)以太網(wǎng)所有的設(shè)備喊出:“這個(gè) IP 地址是誰(shuí)的?請(qǐng)把你的 MAC 地址告訴我”。

          然后就會(huì)有人回答:“這個(gè) IP 地址是我的,我的 MAC 地址是 XXXX”。

          如果對(duì)方和自己處于同一個(gè)子網(wǎng)中,那么通過(guò)上面的操作就可以得到對(duì)方的 MAC 地址。然后,我們將這個(gè) MAC 地址寫(xiě)入 MAC 頭部,MAC 頭部就完成了。

          好像每次都要廣播獲取,這不是很麻煩嗎?

          放心,在后續(xù)操作系統(tǒng)會(huì)把本次查詢(xún)結(jié)果放到一塊叫做 ARP 緩存的內(nèi)存空間留著以后用,不過(guò)緩存的時(shí)間就幾分鐘。

          也就是說(shuō),在發(fā)包時(shí):

          • 先查詢(xún) ARP 緩存,如果其中已經(jīng)保存了對(duì)方的 MAC 地址,就不需要發(fā)送 ARP 查詢(xún),直接使用 ARP 緩存中的地址。
          • 而當(dāng) ARP 緩存中不存在對(duì)方 MAC 地址時(shí),則發(fā)送 ARP 廣播查詢(xún)。

          查看 ARP 緩存內(nèi)容

          在 Linux 系統(tǒng)中,我們可以使用 arp -a 命令來(lái)查看 ARP 緩存的內(nèi)容。

          ARP 緩存內(nèi)容

          MAC 報(bào)文生成

          至此,網(wǎng)絡(luò)包的報(bào)文如下圖。

          MAC 層報(bào)文

          此時(shí),加上了 MAC 頭部的數(shù)據(jù)包萬(wàn)分感謝,說(shuō)道 :“感謝 MAC 大佬,我知道我下一步要去了哪了!我現(xiàn)在有很多頭部兄弟,相信我可以到達(dá)最終的目的地!”。帶著眾多頭部兄弟的數(shù)據(jù)包,終于準(zhǔn)備要出門(mén)了。

          07 出口 —— 網(wǎng)卡

          IP 生成的網(wǎng)絡(luò)包只是存放在內(nèi)存中的一串二進(jìn)制數(shù)字信息,沒(méi)有辦法直接發(fā)送給對(duì)方。因此,我們需要將數(shù)字信息轉(zhuǎn)換為電信號(hào),才能在網(wǎng)線(xiàn)上傳輸,也就是說(shuō),這才是真正的數(shù)據(jù)發(fā)送過(guò)程。

          負(fù)責(zé)執(zhí)行這一操作的是網(wǎng)卡,要控制網(wǎng)卡還需要靠網(wǎng)卡驅(qū)動(dòng)程序。

          網(wǎng)卡驅(qū)動(dòng)從 IP 模塊獲取到包之后,會(huì)將其復(fù)制到網(wǎng)卡內(nèi)的緩存區(qū)中,接著會(huì)其開(kāi)頭加上報(bào)頭和起始幀分界符,在末尾加上用于檢測(cè)錯(cuò)誤的幀校驗(yàn)序列。

          物理層數(shù)據(jù)包

          • 起始幀分界符是一個(gè)用來(lái)表示包起始位置的標(biāo)記
          • 末尾的 FCS(幀校驗(yàn)序列)用來(lái)檢查包傳輸過(guò)程是否有損壞

          最后網(wǎng)卡會(huì)將包轉(zhuǎn)為電信號(hào),通過(guò)網(wǎng)線(xiàn)發(fā)送出去。

          唉,真是不容易,發(fā)一個(gè)包,真是歷經(jīng)歷經(jīng)千辛萬(wàn)苦。致此,一個(gè)帶有許多頭部的數(shù)據(jù)終于踏上尋找目的地的征途了!

          08 送別者 —— 交換機(jī)

          下面來(lái)看一下包是如何通過(guò)交換機(jī)的。交換機(jī)的設(shè)計(jì)是將網(wǎng)絡(luò)包原樣轉(zhuǎn)發(fā)到目的地。交換機(jī)工作在 MAC 層,也稱(chēng)為二層網(wǎng)絡(luò)設(shè)備。

          交換機(jī)的包接收操作

          首先,電信號(hào)到達(dá)網(wǎng)線(xiàn)接口,交換機(jī)里的模塊進(jìn)行接收,接下來(lái)交換機(jī)里的模塊將電信號(hào)轉(zhuǎn)換為數(shù)字信號(hào)。

          然后通過(guò)包末尾的 FCS 校驗(yàn)錯(cuò)誤,如果沒(méi)問(wèn)題則放到緩沖區(qū)。這部分操作基本和計(jì)算機(jī)的網(wǎng)卡相同,但交換機(jī)的工作方式和網(wǎng)卡不同。

          計(jì)算機(jī)的網(wǎng)卡本身具有 MAC 地址,并通過(guò)核對(duì)收到的包的接收方 MAC 地址判斷是不是發(fā)給自己的,如果不是發(fā)給自己的則丟棄;相對(duì)地,交換機(jī)的端口不核對(duì)接收方 MAC 地址,而是直接接收所有的包并存放到緩沖區(qū)中。因此,和網(wǎng)卡不同,交換機(jī)的端口不具有 MAC 地址。

          將包存入緩沖區(qū)后,接下來(lái)需要查詢(xún)一下這個(gè)包的接收方 MAC 地址是否已經(jīng)在 MAC 地址表中有記錄了。

          交換機(jī)的 MAC 地址表主要包含兩個(gè)信息:

          • 一個(gè)是設(shè)備的 MAC 地址,
          • 另一個(gè)是該設(shè)備連接在交換機(jī)的哪個(gè)端口上。

          交換機(jī)的 MAC 地址表

          舉個(gè)例子,如果收到的包的接收方 MAC 地址為 00-02-B3-1C-9C-F9,則與圖中表中的第 3 行匹配,根據(jù)端口列的信息,可知這個(gè)地址位于 3 號(hào)端口上,然后就可以通過(guò)交換電路將包發(fā)送到相應(yīng)的端口了。

          所以,交換機(jī)根據(jù) MAC 地址表查找 MAC 地址,然后將信號(hào)發(fā)送到相應(yīng)的端口。

          當(dāng) MAC 地址表找不到指定的 MAC 地址會(huì)怎么樣?

          地址表中找不到指定的 MAC 地址。這可能是因?yàn)榫哂性摰刂返脑O(shè)備還沒(méi)有向交換機(jī)發(fā)送過(guò)包,或者這個(gè)設(shè)備一段時(shí)間沒(méi)有工作導(dǎo)致地址被從地址表中刪除了。

          這種情況下,交換機(jī)無(wú)法判斷應(yīng)該把包轉(zhuǎn)發(fā)到哪個(gè)端口,只能將包轉(zhuǎn)發(fā)到除了源端口之外的所有端口上,無(wú)論該設(shè)備連接在哪個(gè)端口上都能收到這個(gè)包。

          這樣做不會(huì)產(chǎn)生什么問(wèn)題,因?yàn)橐蕴W(wǎng)的設(shè)計(jì)本來(lái)就是將包發(fā)送到整個(gè)網(wǎng)絡(luò)的,然后只有相應(yīng)的接收者才接收包,而其他設(shè)備則會(huì)忽略這個(gè)包。

          有人會(huì)說(shuō):“這樣做會(huì)發(fā)送多余的包,會(huì)不會(huì)造成網(wǎng)絡(luò)擁塞呢?”

          其實(shí)完全不用過(guò)于擔(dān)心,因?yàn)榘l(fā)送了包之后目標(biāo)設(shè)備會(huì)作出響應(yīng),只要返回了響應(yīng)包,交換機(jī)就可以將它的地址寫(xiě)入 MAC 地址表,下次也就不需要把包發(fā)到所有端口了。

          局域網(wǎng)中每秒可以傳輸上千個(gè)包,多出一兩個(gè)包并無(wú)大礙。

          此外,如果接收方 MAC 地址是一個(gè)廣播地址,那么交換機(jī)會(huì)將包發(fā)送到除源端口之外的所有端口。

          以下兩個(gè)屬于廣播地址:

          • MAC 地址中的 FF:FF:FF:FF:FF:FF
          • IP 地址中的 255.255.255.255

          數(shù)據(jù)包通過(guò)交換機(jī)轉(zhuǎn)發(fā)抵達(dá)了路由器,準(zhǔn)備要離開(kāi)土生土長(zhǎng)的子網(wǎng)了。此時(shí),數(shù)據(jù)包和交換機(jī)離別時(shí)說(shuō)道:“感謝交換機(jī)兄弟,幫我轉(zhuǎn)發(fā)到出境的大門(mén),我要出遠(yuǎn)門(mén)啦!”

          09 出境大門(mén) —— 路由器

          路由器與交換機(jī)的區(qū)別

          網(wǎng)絡(luò)包經(jīng)過(guò)交換機(jī)之后,現(xiàn)在到達(dá)了路由器,并在此被轉(zhuǎn)發(fā)到下一個(gè)路由器或目標(biāo)設(shè)備。

          這一步轉(zhuǎn)發(fā)的工作原理和交換機(jī)類(lèi)似,也是通過(guò)查表判斷包轉(zhuǎn)發(fā)的目標(biāo)。

          不過(guò)在具體的操作過(guò)程上,路由器和交換機(jī)是有區(qū)別的。

          • 因?yàn)槁酚善魇腔?IP 設(shè)計(jì)的,俗稱(chēng)三層網(wǎng)絡(luò)設(shè)備,路由器的各個(gè)端口都具有 MAC 地址和 IP 地址;
          • 而交換機(jī)是基于以太網(wǎng)設(shè)計(jì)的,俗稱(chēng)二層網(wǎng)絡(luò)設(shè)備,交換機(jī)的端口不具有 MAC 地址。

          路由器基本原理

          路由器的端口具有 MAC 地址,因此它就能夠成為以太網(wǎng)的發(fā)送方和接收方;同時(shí)還具有 IP 地址,從這個(gè)意義上來(lái)說(shuō),它和計(jì)算機(jī)的網(wǎng)卡是一樣的。

          當(dāng)轉(zhuǎn)發(fā)包時(shí),首先路由器端口會(huì)接收發(fā)給自己的以太網(wǎng)包,然后路由表查詢(xún)轉(zhuǎn)發(fā)目標(biāo),再由相應(yīng)的端口作為發(fā)送方將以太網(wǎng)包發(fā)送出去。

          路由器的包接收操作

          首先,電信號(hào)到達(dá)網(wǎng)線(xiàn)接口部分,路由器中的模塊會(huì)將電信號(hào)轉(zhuǎn)成數(shù)字信號(hào),然后通過(guò)包末尾的 FCS 進(jìn)行錯(cuò)誤校驗(yàn)。

          如果沒(méi)問(wèn)題則檢查 MAC 頭部中的接收方 MAC 地址,看看是不是發(fā)給自己的包,如果是就放到接收緩沖區(qū)中,否則就丟棄這個(gè)包。

          總的來(lái)說(shuō),路由器的端口都具有 MAC 地址,只接收與自身地址匹配的包,遇到不匹配的包則直接丟棄。

          查詢(xún)路由表確定輸出端口

          完成包接收操作之后,路由器就會(huì)去掉包開(kāi)頭的 MAC 頭部。

          MAC 頭部的作用就是將包送達(dá)路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此,當(dāng)包到達(dá)路由器之后,MAC 頭部的任務(wù)就完成了,于是 MAC 頭部就會(huì)被丟棄。

          接下來(lái),路由器會(huì)根據(jù) MAC 頭部后方的 IP 頭部中的內(nèi)容進(jìn)行包的轉(zhuǎn)發(fā)操作。

          轉(zhuǎn)發(fā)操作分為幾個(gè)階段,首先是查詢(xún)路由表判斷轉(zhuǎn)發(fā)目標(biāo)。

          路由器轉(zhuǎn)發(fā)

          具體的工作流程根據(jù)上圖,舉個(gè)例子。

          假設(shè)地址為 10.10.1.101 的計(jì)算機(jī)要向地址為 192.168.1.100 的服務(wù)器發(fā)送一個(gè)包,這個(gè)包先到達(dá)圖中的路由器。

          判斷轉(zhuǎn)發(fā)目標(biāo)的第一步,就是根據(jù)包的接收方 IP 地址查詢(xún)路由表中的目標(biāo)地址欄,以找到相匹配的記錄。

          路由匹配和前面講的一樣,每個(gè)條目的子網(wǎng)掩碼和 192.168.1.100 IP 做 & 與運(yùn)算后,得到的結(jié)果與對(duì)應(yīng)條目的目標(biāo)地址進(jìn)行匹配,如果匹配就會(huì)作為候選轉(zhuǎn)發(fā)目標(biāo),如果不匹配就繼續(xù)與下個(gè)條目進(jìn)行路由匹配。

          如第二條目的子網(wǎng)掩碼 255.255.255.0 與 192.168.1.100 IP 做 & 與運(yùn)算后,得到結(jié)果是 192.168.1.0 ,這與第二條目的目標(biāo)地址 192.168.1.0 匹配,該第二條目記錄就會(huì)被作為轉(zhuǎn)發(fā)目標(biāo)。

          實(shí)在找不到匹配路由時(shí),就會(huì)選擇默認(rèn)路由,路由表中子網(wǎng)掩碼為 0.0.0.0 的記錄表示「默認(rèn)路由」。

          路由器的發(fā)送操作

          接下來(lái)就會(huì)進(jìn)入包的發(fā)送操作。

          首先,我們需要根據(jù)路由表的網(wǎng)關(guān)列判斷對(duì)方的地址。

          • 如果網(wǎng)關(guān)是一個(gè) IP 地址,則這個(gè)IP 地址就是我們要轉(zhuǎn)發(fā)到的目標(biāo)地址,還未抵達(dá)終點(diǎn),還需繼續(xù)需要路由器轉(zhuǎn)發(fā)。
          • 如果網(wǎng)關(guān)為空,則 IP 頭部中的接收方 IP 地址就是要轉(zhuǎn)發(fā)到的目標(biāo)地址,也是就終于找到 IP 包頭里的目標(biāo)地址了,說(shuō)明已抵達(dá)終點(diǎn)。

          知道對(duì)方的 IP 地址之后,接下來(lái)需要通過(guò) ARP 協(xié)議根據(jù) IP 地址查詢(xún) MAC 地址,并將查詢(xún)的結(jié)果作為接收方 MAC 地址。

          路由器也有 ARP 緩存,因此首先會(huì)在 ARP 緩存中查詢(xún),如果找不到則發(fā)送 ARP 查詢(xún)請(qǐng)求。

          接下來(lái)是發(fā)送方 MAC 地址字段,這里填寫(xiě)輸出端口的 MAC 地址。還有一個(gè)以太類(lèi)型字段,填寫(xiě) 0080 (十六進(jìn)制)表示 IP 協(xié)議。

          網(wǎng)絡(luò)包完成后,接下來(lái)會(huì)將其轉(zhuǎn)換成電信號(hào)并通過(guò)端口發(fā)送出去。這一步的工作過(guò)程和計(jì)算機(jī)也是相同的。

          發(fā)送出去的網(wǎng)絡(luò)包會(huì)通過(guò)交換機(jī)到達(dá)下一個(gè)路由器。由于接收方 MAC 地址就是下一個(gè)路由器的地址,所以交換機(jī)會(huì)根據(jù)這一地址將包傳輸?shù)较乱粋€(gè)路由器。

          接下來(lái),下一個(gè)路由器會(huì)將包轉(zhuǎn)發(fā)給再下一個(gè)路由器,經(jīng)過(guò)層層轉(zhuǎn)發(fā)之后,網(wǎng)絡(luò)包就到達(dá)了最終的目的地。

          不知你發(fā)現(xiàn)了沒(méi)有,在網(wǎng)絡(luò)包傳輸?shù)倪^(guò)程中,源 IP 和目標(biāo) IP 始終是不會(huì)變的,一直變化的是 MAC 地址,因?yàn)樾枰?MAC 地址在以太網(wǎng)內(nèi)進(jìn)行兩個(gè)設(shè)備之間的包傳輸。

          數(shù)據(jù)包通過(guò)多個(gè)路由器道友的幫助,在網(wǎng)絡(luò)世界途徑了很多路程,最終抵達(dá)了目的地的城門(mén)!城門(mén)值守的路由器,發(fā)現(xiàn)了這個(gè)小兄弟數(shù)據(jù)包原來(lái)是找城內(nèi)的人,于是它就將數(shù)據(jù)包送進(jìn)了城內(nèi),再經(jīng)由城內(nèi)的交換機(jī)幫助下,最終轉(zhuǎn)發(fā)到了目的地了。數(shù)據(jù)包感慨萬(wàn)千的說(shuō)道:“多謝這一路上,各路大俠的相助!”

          10 互相扒皮 —— 服務(wù)器 與 客戶(hù)端

          數(shù)據(jù)包抵達(dá)了服務(wù)器,服務(wù)器肯定高興呀,正所謂有朋自遠(yuǎn)方來(lái),不亦樂(lè)乎?

          服務(wù)器高興的不得了,于是開(kāi)始扒數(shù)據(jù)包的皮!就好像你收到快遞,能不興奮嗎?

          扒皮模型

          數(shù)據(jù)包抵達(dá)服務(wù)器后,服務(wù)器會(huì)先扒開(kāi)數(shù)據(jù)包的 MAC 頭部,查看是否和服務(wù)器自己的 MAC 地址符合,符合就將包收起來(lái)。

          接著繼續(xù)扒開(kāi)數(shù)據(jù)包的 IP 頭,發(fā)現(xiàn) IP 地址符合,根據(jù) IP 頭中協(xié)議項(xiàng),知道自己上層是 TCP 協(xié)議。

          于是,扒開(kāi) TCP 的頭,里面有序列號(hào),需要看一看這個(gè)序列包是不是我想要的,如果是就放入緩存中然后返回一個(gè) ACK,如果不是就丟棄。TCP頭部里面還有端口號(hào), HTTP 的服務(wù)器正在監(jiān)聽(tīng)這個(gè)端口號(hào)。

          于是,服務(wù)器自然就知道是 HTTP 進(jìn)程想要這個(gè)包,于是就將包發(fā)給 HTTP 進(jìn)程。

          服務(wù)器的 HTTP 進(jìn)程看到,原來(lái)這個(gè)請(qǐng)求是要訪問(wèn)一個(gè)頁(yè)面,于是就把這個(gè)網(wǎng)頁(yè)封裝在

          HTTP 響應(yīng)報(bào)文里。

          HTTP 響應(yīng)報(bào)文也需要穿上 TCP、IP、MAC 頭部,不過(guò)這次是源地址是服務(wù)器 IP 地址,目的地址是客戶(hù)端 IP 地址。

          穿好頭部衣服后,從網(wǎng)卡出去,交由交換機(jī)轉(zhuǎn)發(fā)到出城的路由器,路由器就把響應(yīng)數(shù)據(jù)包發(fā)到了下一個(gè)路由器,就這樣跳啊跳。

          最后跳到了客戶(hù)端的城門(mén)把手的路由器,路由器扒開(kāi) IP 頭部發(fā)現(xiàn)是要找城內(nèi)的人,于是把包發(fā)給了城內(nèi)的交換機(jī),再由交換機(jī)轉(zhuǎn)發(fā)到客戶(hù)端。

          客戶(hù)端收到了服務(wù)器的響應(yīng)數(shù)據(jù)包后,同樣也非常的高興,客戶(hù)能拆快遞了!

          于是,客戶(hù)端開(kāi)始扒皮,把收到的數(shù)據(jù)包的皮扒剩 HTTP 響應(yīng)報(bào)文后,交給瀏覽器去渲染頁(yè)面,一份特別的數(shù)據(jù)包快遞,就這樣顯示出來(lái)了!

          最后,客戶(hù)端要離開(kāi)了,向服務(wù)器發(fā)起了 TCP 四次揮手,至此雙方的連接就斷開(kāi)了。

          一個(gè)數(shù)據(jù)包臭不要臉的感受

          下面內(nèi)容的 「我」,代表「臭美的數(shù)據(jù)包角色」。
          (括號(hào)的內(nèi)容)代表我的吐槽,三連呸!

          一開(kāi)始我雖然孤單、不知所措,但沒(méi)有停滯不前。我依然滿(mǎn)懷信心和勇氣開(kāi)始了征途。(你當(dāng)然有勇氣,你是應(yīng)用層數(shù)據(jù),后面有底層兄弟當(dāng)靠山,我呸!)

          我很慶幸遇到了各路神通廣大的大佬,有可靠傳輸?shù)?TCP、有遠(yuǎn)程定位功能的 IP、有指明下一站位置的 MAC 等(你當(dāng)然會(huì)遇到,因?yàn)槎急挥?jì)算機(jī)安排好的,我呸!)。

          這些大佬都給我前面加上了頭部,使得我能在交換機(jī)和路由器的轉(zhuǎn)發(fā)下,抵達(dá)到了目的地!(哎,你也不容易,不吐槽了,放過(guò)你!)

          這一路上的經(jīng)歷,讓我認(rèn)識(shí)到了網(wǎng)絡(luò)世界中各路大俠協(xié)作的重要性,是他們維護(hù)了網(wǎng)絡(luò)世界的秩序,感謝他們!(我呸,你應(yīng)該感謝眾多計(jì)算機(jī)科學(xué)家!)

          喜歡請(qǐng)多多關(guān)注易杰智科技!

          、為什么要了解常見(jiàn)JS錯(cuò)誤

          1、調(diào)試和故障排除:

          了解常見(jiàn)的JavaScript錯(cuò)誤可以幫助你更好地調(diào)試和故障排除代碼。當(dāng)你遇到錯(cuò)誤時(shí),能夠快速識(shí)別錯(cuò)誤類(lèi)型并找到解決方法,可以節(jié)省大量的時(shí)間和精力。

          2、代碼質(zhì)量和穩(wěn)定性:

          通過(guò)了解常見(jiàn)的JavaScript錯(cuò)誤,你可以編寫(xiě)更健壯和穩(wěn)定的代碼。你可以預(yù)先考慮到可能出現(xiàn)的錯(cuò)誤情況,并采取適當(dāng)?shù)拇胧﹣?lái)處理或避免這些錯(cuò)誤,從而提高代碼的質(zhì)量和穩(wěn)定性。

          3、用戶(hù)體驗(yàn)(很重要):

          JavaScript錯(cuò)誤可能會(huì)導(dǎo)致應(yīng)用程序崩潰、功能失效或不可預(yù)料的行為。通過(guò)了解常見(jiàn)的JavaScript錯(cuò)誤并處理它們,可以提供更好的用戶(hù)體驗(yàn),避免應(yīng)用程序因錯(cuò)誤而中斷或表現(xiàn)不正常。

          4、安全性:

          某些JavaScript錯(cuò)誤可能會(huì)暴露應(yīng)用程序的漏洞,使其易受攻擊。了解這些錯(cuò)誤并采取適當(dāng)?shù)陌踩胧┛梢詭椭惚Wo(hù)應(yīng)用程序免受潛在的安全威脅。

          5、學(xué)習(xí)和成長(zhǎng):

          通過(guò)了解常見(jiàn)的JavaScript錯(cuò)誤,你可以不斷學(xué)習(xí)和成長(zhǎng)。你可以深入了解錯(cuò)誤的原因、背后的概念和解決方法,從而提高自己的技能和知識(shí)水平。

          二、以下JS報(bào)錯(cuò)的一些常見(jiàn)影響:

          1、程序中斷:

          JS報(bào)錯(cuò)會(huì)導(dǎo)致程序的執(zhí)行中斷,代碼無(wú)法繼續(xù)執(zhí)行下去。

          2、功能異常:

          報(bào)錯(cuò)可能導(dǎo)致程序的功能異常或不可用。例如,如果某個(gè)關(guān)鍵函數(shù)報(bào)錯(cuò),可能會(huì)導(dǎo)致相關(guān)功能無(wú)法正常運(yùn)行。

          3、頁(yè)面崩潰:

          嚴(yán)重的JS報(bào)錯(cuò)可能導(dǎo)致整個(gè)頁(yè)面崩潰,無(wú)法正常顯示或交互。

          4、錯(cuò)誤信息暴露:

          報(bào)錯(cuò)信息可能會(huì)被顯示在頁(yè)面上,這可能會(huì)泄露敏感信息,給攻擊者提供潛在的安全漏洞。

          5、用戶(hù)體驗(yàn)下降:

          JS報(bào)錯(cuò)可能會(huì)導(dǎo)致頁(yè)面加載緩慢或卡頓,影響用戶(hù)的體驗(yàn)。

          6、數(shù)據(jù)丟失:

          某些報(bào)錯(cuò)可能會(huì)導(dǎo)致數(shù)據(jù)丟失或損壞,特別是在涉及到數(shù)據(jù)處理或存儲(chǔ)的情況下。

          7、兼容性問(wèn)題:

          不同瀏覽器對(duì)JS的處理方式可能不同,報(bào)錯(cuò)可能會(huì)導(dǎo)致兼容性問(wèn)題,使得頁(yè)面在某些瀏覽器上無(wú)法正常工作。

          因此,及時(shí)處理和修復(fù)JS報(bào)錯(cuò)是非常重要的,以確保程序的正常運(yùn)行和用戶(hù)體驗(yàn)。

          三、有哪些常見(jiàn)錯(cuò)誤及相應(yīng)示例說(shuō)明

          1、TypeError 類(lèi)型錯(cuò)誤:

          var num=666;
          num(); 
          // Uncaught TypeError: num is not a function
          
          

          解決方法:確保你對(duì)值的操作和使用是符合其類(lèi)型的。

          2、ReferenceError引用錯(cuò)誤:

          console.log(foo); 
          // Uncaught ReferenceError: foo is not defined
          
          

          解決方法:確保你在使用變量或函數(shù)之前進(jìn)行了正確的聲明和定義。

          3、SyntaxError語(yǔ)法錯(cuò)誤:

          if (x > 5 { // 缺少右括號(hào)
            console.log('x is greater than 5');
          }
          //  Uncaught SyntaxError: Unexpected token '{'
          
          

          解決方法:仔細(xì)檢查代碼,確保語(yǔ)法正確,例如括號(hào)匹配、分號(hào)使用等。

          4、RangeError范圍錯(cuò)誤:

          function recursiveFunction() {
              recursiveFunction();
          }
          recursiveFunction();
          //  Uncaught RangeError: Maximum call stack size exceeded
          
          

          解決方法:確保你在訪問(wèn)數(shù)組、字符串或其他可迭代對(duì)象時(shí),使用的索引或位置在有效范圍內(nèi)。

          function recursiveFunction(depth) {

          if (depth===0) {

          return;

          }

          recursiveFunction(depth - 1);

          }

          recursiveFunction(100);

          // 在這個(gè)示例中,我們通過(guò)增加一個(gè)停止條件來(lái)修復(fù)范圍錯(cuò)誤。遞歸的深度被限制在100次。

          5、EvalErroreval 函數(shù)錯(cuò)誤:

          在JavaScript中,EvalError是一個(gè)錯(cuò)誤類(lèi)型,表示與eval()函數(shù)相關(guān)的錯(cuò)誤。然而,在現(xiàn)代的JavaScript環(huán)境中,EvalError的使用相對(duì)較少。 示例:

          eval('alert("Hello, World!");'); 
          // 我們使用eval()函數(shù)來(lái)執(zhí)行一個(gè)字符串作為JavaScript代碼。如果字符串中的代碼存在語(yǔ)法錯(cuò)誤或其他問(wèn)題,就會(huì)拋出EvalError。
          
          

          解決方法:避免使用 eval 函數(shù),盡量使用其他更安全的替代方法。例如使用Function構(gòu)造函數(shù)或解析器工具等。

          6、URIErrorURI 錯(cuò)誤:

          decodeURIComponent('%'); 
          // Uncaught URIError: URI malformed
          
          

          解決方法:確保你在使用 URI 相關(guān)函數(shù)或方法時(shí),提供的參數(shù)是合法的。

          7、InternalError內(nèi)部錯(cuò)誤:

          function createHugeArray() {
            var arr=new Array(2000000000);
            return arr;
          }
          createHugeArray()
          
          

          解決方法:InternalError通常是由于JavaScript引擎或運(yùn)行時(shí)環(huán)境中的內(nèi)部問(wèn)題導(dǎo)致的,例如堆棧溢出、內(nèi)存不足等。避免出現(xiàn)無(wú)限遞歸、死循環(huán)等問(wèn)題,確保你的代碼邏輯正確。

          8、AsyncError異步錯(cuò)誤:

          async function fetchData() {
            throw new Error('Something went wrong'); // 拋出一個(gè)錯(cuò)誤
          }
          fetchData()
            .catch(error=> {
              console.log('Async error:', error); // 捕獲異步錯(cuò)誤并進(jìn)行處理
            });
          
          
          

          解決方法:使用適當(dāng)?shù)腻e(cuò)誤處理機(jī)制,例如使用 try-catch 或 catch 方法來(lái)捕獲和處理異步錯(cuò)誤。

          async function fetchData() {

          try {

          throw new Error('Something went wrong'); // 拋出一個(gè)錯(cuò)誤

          } catch (error) {

          console.log('Sync error:', error); // 捕獲同步錯(cuò)誤并進(jìn)行處理 }}

          fetchData()

          .catch(error=> {

          console.log('Async error:', error); // 捕獲異步錯(cuò)誤并進(jìn)行處理

          });

          四、了解后的實(shí)踐和能收獲什么

          1. 錯(cuò)誤處理和異常處理是前端開(kāi)發(fā)中不可或缺的一部分,能夠提升用戶(hù)體驗(yàn),減少用戶(hù)流失率:

          綜合上述幾種異常錯(cuò)誤,在部門(mén)小程序項(xiàng)目中進(jìn)行了JS報(bào)錯(cuò)異常優(yōu)化,第一版本優(yōu)化后錯(cuò)誤數(shù)上線(xiàn)后由每日最高1374次降低到184次,減少了近86%的錯(cuò)誤次數(shù),由錯(cuò)誤人數(shù) 694降低到109人,減少了近84%錯(cuò)誤人數(shù)。







          2.了解常見(jiàn)錯(cuò)誤類(lèi)型和異常類(lèi)型,以及相應(yīng)的解決方法,可以幫助我們更好地定位和解決問(wèn)題。

          3. 示例提供了一些常見(jiàn)錯(cuò)誤的解決方法,但實(shí)際情況可能因代碼和環(huán)境而異,需要仔細(xì)分析和調(diào)試代碼。

          4. 參考文章提供了更多學(xué)習(xí)資源和深入了解錯(cuò)誤處理的內(nèi)容。

          五、參考文章(部分內(nèi)容GPT生成)

          ?MDN Web 文檔:https://developer.mozilla.org/

          ?JavaScript 教程 - W3Schools:https://www.w3schools.com/js/

          ?JavaScript 錯(cuò)誤處理和調(diào)試 - JavaScript.info:https://javascript.info/try-catch

          ?JavaScript 異常處理的藝術(shù) - Smashing Magazine:https://www.smashingmagazine.com/2020/08/error-handling-art-javascript/

          ?JavaScript 異常處理的 8 個(gè)技巧 - SitePoint:https://blog.logrocket.com/5-common-javascript-exception-handling-mistakes/


          作者:京東零售 孫鵬紅

          來(lái)源:京東云開(kāi)發(fā)者社區(qū) 轉(zhuǎn)載請(qǐng)注明來(lái)源

          、新建項(xiàng)目

          1、新建===web項(xiàng)目===輸入項(xiàng)目名稱(chēng)====完成


          二、新建html文件

          在新建項(xiàng)目中新建html模板


          輸入文件名稱(chēng):


          三、認(rèn)識(shí)基本格式


          聯(lián)想出基本格式:



          四、編輯html文件


          運(yùn)行html,選擇瀏覽器



          五、html常用的快捷鍵

          (1)ctrl+n+w web項(xiàng)目創(chuàng)建



          (2)ctrl+n+h html文檔創(chuàng)建


          (3)ctrl+s 保存html頁(yè)面(頁(yè)面上如果未保存會(huì)顯示*號(hào))



          (4)ctrl+r html運(yùn)行
          (5)ctrl+z 撤回
          (6)!+tab鍵 聯(lián)想基本格式
          (7)ctrl+/ 注釋和取消注釋



          (8)ctrl+鼠標(biāo)滾輪, 字體方大和縮小


          六、認(rèn)識(shí)標(biāo)簽

          (1)H標(biāo)簽(標(biāo)題標(biāo)簽)



          (2)p標(biāo)簽 (段落標(biāo)簽)



          (3)img 標(biāo)簽(圖片標(biāo)簽)
          兩種:第一種widows上傳圖片,第二種:網(wǎng)上圖片鏈接

          第一種


          img中顯示圖片

          img中引入圖片




          第二種:網(wǎng)上圖片的鏈接:




          (4) 標(biāo)簽(空格)



          (5)em 標(biāo)簽表示斜體



          (6)i 標(biāo)簽表示斜體



          (7)br 表示換行



          (8)b 標(biāo)簽表示加粗



          (9) strong 標(biāo)簽表示加粗



          (10)s 標(biāo)簽(刪除線(xiàn))




          (11)u 標(biāo)簽 (下劃線(xiàn))



          (12)font 顏色



          (13)sub下標(biāo)
          (14)sup上標(biāo)


          主站蜘蛛池模板: 国产免费一区二区视频| 亚洲AV噜噜一区二区三区| 国产精品区一区二区三在线播放| 亚洲av无码一区二区三区乱子伦| 日本福利一区二区| 亚洲AV无码一区二区三区性色| 乱色熟女综合一区二区三区| 亚洲乱码av中文一区二区| 日韩精品无码一区二区三区四区 | 亲子乱av一区区三区40岁| 午夜影视日本亚洲欧洲精品一区 | 国产福利在线观看一区二区| 老熟女高潮一区二区三区| 无码人妻AⅤ一区二区三区 | 亚洲AV美女一区二区三区| 国产伦一区二区三区高清 | 精品国产一区二区三区www| 国产91大片精品一区在线观看| 国产在线一区二区| 亚洲成AV人片一区二区| 在线观看午夜亚洲一区| 久久se精品一区二区| 国产一区二区在线看| 一区二区三区在线|欧| 精品一区二区三区免费毛片爱| 久久久久无码国产精品一区| 亚洲国产一区二区a毛片| 亚洲无圣光一区二区| 毛片一区二区三区| 无码人妻精品一区二区三区9厂| 在线|一区二区三区四区| 在线成人综合色一区| 一区视频在线播放| 亚洲无人区一区二区三区| 无码精品一区二区三区在线| 国产精品亚洲午夜一区二区三区| 在线观看国产一区二三区| 99国产精品欧美一区二区三区| 后入内射国产一区二区| 国产伦精品一区二区三区视频猫咪| 国模少妇一区二区三区|