整合營銷服務(wù)商

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

          免費(fèi)咨詢熱線:

          JavaScript全解析-DOM事件(上)

          JavaScript全解析-DOM事件(上)

          OM 事件

          ●是指用戶在某事務(wù)上由于某種行為所執(zhí)行的操作; (對頁面元素的某種操作)
          ●一個(gè)事件由哪幾部分組成
          ○觸發(fā)誰的事件:事件源
          ○觸發(fā)什么事件:事件類型
          ○觸發(fā)以后做什么:事件處理函數(shù)(事件處理程序)

          var oDiv=document.querySelector('div')
          
          oDiv.onclick=function () {}
          // 誰來觸發(fā)事件=> oDiv=> 這個(gè)事件的事件源就是 oDiv
          // 觸發(fā)什么事件=> onclick=> 這個(gè)事件類型就是 click
          // 觸發(fā)之后做什么=> function () {}=> 這個(gè)事件的處理函數(shù)

          ●我們想要在點(diǎn)擊 div 以后做什么事情,就把我們要做的事情寫在事件處理函數(shù)里面


          var oDiv=document.querySelector('div')
          
          oDiv.onclick=function () {
            console.log('你點(diǎn)擊了 div')
          }

          ●當(dāng)我們點(diǎn)擊 div 的時(shí)候,就會執(zhí)行事件處理函數(shù)內(nèi)部的代碼
          ●每點(diǎn)擊一次,就會執(zhí)行一次事件處理函數(shù)

          事件綁定和事件解綁

          事件綁定

          ●事件綁定有DOM 0級和DOM 2級
          ●沒有DOM 1級
          ○DOM級別1于1998年10月1日成為W3C推薦標(biāo)準(zhǔn)。1級DOM標(biāo)準(zhǔn)中并沒有定義事件相關(guān)的內(nèi)容,所以沒有所謂的1級DOM事件模型。在2級DOM中除了定義了一些DOM相關(guān)的操作之外還定義了一個(gè)事件模型 ,這個(gè)標(biāo)準(zhǔn)下的事件模型就是我們所說的2級DOM事件模型
          DOM 0級事件綁定
          ●我們現(xiàn)在給一個(gè)注冊事件都是使用 onxxx 的方式
          ●但是這個(gè)方式不是很好,只能給一個(gè)事件源的同一個(gè)事件類型, 只能綁定一個(gè)事件處理函數(shù)
          ●一旦寫了第二個(gè)事件,那么第一個(gè)就被覆蓋了
          ●語法:事件源.onclick=事件處理程序(事件處理函數(shù))

          oDiv.onclick=function () {
            console.log('我是第一個(gè)事件')
          }
          
          oDiv.onclick=function () {
            console.log('我是第二個(gè)事件')
          }

          ●當(dāng)你點(diǎn)擊的時(shí)候,只會執(zhí)行第二個(gè),第一個(gè)就沒有了

          DOM 2級事件綁定 事件監(jiān)聽

          標(biāo)準(zhǔn)瀏覽器
          ●使用 addEventListener 的方式添加。addEventListener : 非 IE 7 8 下使用
          ●語法: 元素.addEventListener('事件類型', 事件處理函數(shù), 冒泡還是捕獲)
          ●可以給同一個(gè)事件源的同一個(gè)事件類型綁定多個(gè)事件處理函數(shù)

          oDiv.addEventListener('click', function () {
            console.log('我是第一個(gè)事件')
          }, false)
          
          oDiv.addEventListener('click', function () {
            console.log('我是第二個(gè)事件')
          }, false)

          ●當(dāng)你點(diǎn)擊 div 的時(shí)候,兩個(gè)函數(shù)都會執(zhí)行,并且會按照你注冊的順序執(zhí)行
          ●先打印 我是第一個(gè)事件 再打印 我是第二個(gè)事件
          ●注意: 事件類型的時(shí)候不要寫 on,點(diǎn)擊事件就是 click,不是 onclick

          IE低版本瀏覽器

          ●attachEvent :IE 7 8 下使用
          ●語法: 元素.attachEvent('事件類型', 事件處理函數(shù))
          ●可以給同一個(gè)事件源的同一個(gè)事件類型綁定多個(gè)事件處理函數(shù)

          oDiv.attachEvent('onclick', function () {
            console.log('我是第一個(gè)事件')
          })
          
          oDiv.attachEvent('onclick', function () {
            console.log('我是第二個(gè)事件')
          })

          ●當(dāng)你點(diǎn)擊 div 的時(shí)候,兩個(gè)函數(shù)都會執(zhí)行,并且會按照你注冊的順序倒敘執(zhí)行
          ●先打印 我是第二個(gè)事件 再打印 我是第一個(gè)事件
          ●注意: 事件類型的時(shí)候要寫 on,點(diǎn)擊事件就行 onclick
          兩個(gè)方式的區(qū)別
          ●注冊事件的時(shí)候事件類型參數(shù)的書寫
          ○addEventListener : 不用寫 on
          ○attachEvent : 要寫 on
          ●參數(shù)個(gè)數(shù)
          ○addEventListener : 一般是三個(gè)常用參數(shù)
          ○attachEvent : 兩個(gè)參數(shù)
          ●執(zhí)行順序
          ○addEventListener : 順序注冊,順序執(zhí)行
          ○attachEvent : 順序注冊,倒敘執(zhí)行
          ●適用瀏覽器
          ○addEventListener : 非 IE 7 8 的瀏覽器
          ○attachEvent : IE 7 8 瀏覽器

          事件解綁

          DOM 0級事件解綁

          ●語法:事件源.on事件類型=null
          ●因?yàn)橘x值符號, 當(dāng)你給這個(gè)事件類型賦值為 null 的時(shí)候,會把本身的事件處理函數(shù)覆蓋
          ●當(dāng)你再次觸發(fā)行為的時(shí)候, 沒有事件處理函數(shù)執(zhí)行,相當(dāng)于解綁了事

          <!DOCTYPE html>
          <html lang="en">
          
          <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta http-equiv="X-UA-Compatible" content="ie=edge">
              <title>Document</title>
              <style>
                  div {
                      width: 200px;
                      height: 200px;
                      background-color: pink;
                  }
              </style>
          </head>
          
          <body>
          
              <button>事件解綁</button>
          
              <div></div>
          
              <script>
                  // 0. 獲取元素
                  var div=document.getElementsByTagName('div')[0]
                  var btn=document.getElementsByTagName('button')[0]
          
                  // 1. DOM 0級 綁定事件
                  div.onclick=function() {
                      console.log('你好 世界')
                  }
          
                  btn.onclick=function() {
                      console.log('在這里操作解綁 div 的事件')
          
                      // 1. DOM 0級 事件解綁
                      div.onclick=null
          
                      console.log('解綁事件的代碼執(zhí)行完畢了')
                  }
              </script>
          </body>
          
          </html>

          DOM 2級事件解綁

          標(biāo)準(zhǔn)瀏覽器
          ●語法:事件源.removeEventListener('事件類型', 事件處理函數(shù))
          ●注意:
          ○當(dāng)你使用 DOM 2級 事件解綁的時(shí)候, 因?yàn)楹瘮?shù)是一個(gè)復(fù)雜數(shù)據(jù)類型, 所以你在綁定的時(shí)候
          ○需要把函數(shù)單獨(dú)書寫出來, 以函數(shù)名的形式進(jìn)行綁定和解綁

          么理解DOM模型?

          DOM模型(Document Object Model)中文又稱文檔對象模型定義了用戶操作文檔對象的接口,對于這句話可能有點(diǎn)懵。你可以這樣理解它,DOM模型把文檔(html和xml)抽象成供開發(fā)者操作的接口,允許程序和腳本(JavaScript、python等))訪問和更新文檔(html和xml)的內(nèi)容、結(jié)構(gòu)和樣式。DOM模型誕生和JavaScript有很大的關(guān)系,現(xiàn)在不僅僅JavaScript在使用其他語言也在使用。DOM使得用戶對HTML的控制有了空前的訪問和控制能力,并使開發(fā)者將HTML作為XML文檔來處理。

          網(wǎng)頁中的DOM模型框架

          為了大家更好理解DOM模型先說一下網(wǎng)頁中的DOM模型框架,先看1張圖片

          <html>標(biāo)記位于文檔最頂端,他沒有父元素,成為DOM的根節(jié)點(diǎn)。再往下<html>有<head>和<body>兩個(gè)分支,他們同在一層互不包括,屬于兄弟關(guān)系,有著共同的父元素<html>。再往下看<head>有兩個(gè)子元素<head>和<title>,它們互為兄弟。而<body>有3個(gè)子元素,分別是<h2>、<p>和<ul>,<h2>和<ul>都有自己的子元素。有這個(gè)完整的關(guān)系劃分,html文檔結(jié)構(gòu)也清晰可見,各個(gè)元素很容易表達(dá)出來,這就是DOM完成的。

          DOM模型中的節(jié)點(diǎn)

          節(jié)點(diǎn)(node)代表網(wǎng)絡(luò)的連接點(diǎn),網(wǎng)絡(luò)就是節(jié)點(diǎn)構(gòu)成的集合。DOM情況也很類似,文檔可以說是節(jié)點(diǎn)構(gòu)成的集合。在DOM中有3種節(jié)點(diǎn),分別是元素節(jié)點(diǎn)、文本節(jié)點(diǎn)和屬性節(jié)點(diǎn)。

          1、元素節(jié)點(diǎn)

          上圖顯示的<html>、<body>、<meta>、<h2>、<p>等都可以看做節(jié)點(diǎn),各種標(biāo)簽就是這些元素節(jié)點(diǎn)的名稱,例如文本段落元素的名稱是"p",元素節(jié)點(diǎn)是包含其他的元素。

          2、文本節(jié)點(diǎn)

          在HTML中光有標(biāo)記搭建框架是不夠的,頁面最終目的是向用戶展示內(nèi)容。上圖中的<h2>標(biāo)記中有文本“標(biāo)題”,項(xiàng)目列表<li>中有A、B、C、D。這些具體的文本在DOM模型中稱為文本節(jié)點(diǎn)(text node)。并不是所有的元素節(jié)點(diǎn)都包含文本節(jié)點(diǎn)。

          3、屬性節(jié)點(diǎn)

          作為頁面中的元素,大部分都包含屬性,例如大部分元素都有一個(gè)title屬性。我們可以利用這些屬性來對包含在元素的對象作出精確的描述,例如a標(biāo)簽里有title=“D”,那么D就是a標(biāo)簽的屬性,也是a的屬性節(jié)點(diǎn)(attribute node)。屬性包括在標(biāo)簽里,屬性節(jié)點(diǎn)總是被包含在元素節(jié)點(diǎn)中。

          使用DOM

          對于每一個(gè)DOM節(jié)點(diǎn)node,都有一系列屬性、方法可以使用,為大家介紹DOM經(jīng)常使用節(jié)點(diǎn)操作方法,下圖示常用的屬性和方法:

          1、訪問節(jié)點(diǎn)

          最常用的是getElementsByTagName()和getElementById()。getElementsByTagName()用來返回一個(gè)包含某個(gè)相同標(biāo)簽名的元素的nodelist。例如<p>標(biāo)簽標(biāo)簽的標(biāo)簽名為"p",vor oP=getElementsByTagName("P"),返回文檔中所有的p元素。

          2、檢測節(jié)點(diǎn)類型

          通過節(jié)點(diǎn)的nodeType屬性可檢測節(jié)點(diǎn)的類型。該屬性返回一個(gè)代表節(jié)點(diǎn)類型的整數(shù)值,總共有12個(gè)可取的值,如alert(document.nodetype);,可以對某種類型的節(jié)點(diǎn)做單獨(dú)處理。

          3、利用父子兄弟關(guān)系查找節(jié)點(diǎn)

          為了獲取某個(gè)節(jié)點(diǎn)后,可以通過父子關(guān)系,利用hasChildNodes()方法和childNodes屬性獲取該節(jié)點(diǎn)包含的所有的子節(jié)點(diǎn)。

          4、設(shè)置節(jié)點(diǎn)屬性

          在找到需要的節(jié)點(diǎn)之后通常希望對其屬性做相應(yīng)的設(shè)置,DOM定義了兩個(gè)便捷的方法來查詢和節(jié)點(diǎn)的屬性,即getAttribute()方法和setAttribute()方法。

          5、創(chuàng)建、添加、替換、插入節(jié)點(diǎn)操作

          除了查找節(jié)點(diǎn)屬性以外,DOM同樣提供了很多便捷的方法來管理節(jié)點(diǎn),主要包括創(chuàng)建節(jié)點(diǎn)(createElement())、刪除節(jié)點(diǎn)(removechild())、替換節(jié)點(diǎn)(replacechild())和插入(insertBefore())等操作

          關(guān)于盒子DOM模型,上面總結(jié)都是最簡單的,一定要多多練習(xí)孰能生巧。每天學(xué)習(xí)一個(gè)知識點(diǎn),每日寄語-“是非天天有,不聽自然無。”

          者 | MageByte團(tuán)隊(duì)

          來源 | 碼哥字節(jié)(ID:MageByte)

          頭圖 | CSDN 下載自東方IC

          詳解輸入網(wǎng)址點(diǎn)擊回車,后臺到底發(fā)生了什么。透析 HTTP 協(xié)議與 TCP 連接之間的千絲萬縷的關(guān)系。掌握為何是三次握手四次揮手?time_wait 存在的意義是什么?全面圖解重點(diǎn)問題,再也不用擔(dān)心面試問這個(gè)問題。

          大致流程

          • URL 解析,解析 http 協(xié)議、端口、資源地址。

          • DNS 查詢:首先查詢本地 host,再訪問 DNS 服務(wù)器將 域名解析成 ip 地址。

          • 建立 TCP 連接。

          • 服務(wù)器收到請求后處理,并且構(gòu)造響應(yīng)返回給客戶端。

          • 客戶端接收 HTTP 報(bào)文響應(yīng)。

          • 渲染頁面,最后有可能會四次揮手?jǐn)嚅_連接,也可能不會而是復(fù)用連接。

          重點(diǎn)來了:

          • 如何理解 TCP 的三次握手與四次揮手?每次握手客戶端與服務(wù)端是怎樣的狀態(tài)?

          • 為何揮手會出現(xiàn) 2MSL,遇到大量 Socket 處在 TIME_WAIT 或者 CLOSE_WAIT 狀態(tài)是什么問題?

          • 三次握手與四次揮手的過程是怎樣的?

          • HTTP 的報(bào)文格式又是怎樣的?

          繼續(xù)閱讀本文,且聽碼哥字節(jié)答疑解惑,微信搜索 “碼哥字節(jié)”,關(guān)注公眾號更多硬核。

          URL 解析

          比如【碼哥字節(jié)】在思否發(fā)布的一篇文章的地址:https://segmentfault.com/a/1190000023475177。url 遵守的規(guī)則是這個(gè)樣子

          scheme://host.domain:port/path/filename

          每個(gè)名詞的含義如下解釋:

          • scheme 定義應(yīng)用層協(xié)議類型,比如 http、https、 ftp 等;

          • host 定義域主機(jī)(http 的默認(rèn)主機(jī)是 www);

          • domain 定義因特網(wǎng)域名,比如 segmentfault.com;

          • port 主機(jī)的端口,http 默認(rèn)是 80, https 默認(rèn)是 443;

          • path 服務(wù)器上的資源路徑;

          • filename - 定義文檔/資源的名稱;

          DNS 查詢

          瀏覽器不能直接通過域名找到服務(wù)器,只能通過 IP 地址。

          那瀏覽器是如何通過域名查詢到我們輸入的 url 對應(yīng)的 IP 呢?

          • 瀏覽器緩存:按照一定頻率緩存 DNS 數(shù)據(jù)。

          • 操作系統(tǒng)緩存:如果瀏覽器緩存好啊不到記錄則去操作系統(tǒng)中找。

          • 路由緩存:路由器 DNS 緩存。

          • ISP 的 DNS 服務(wù)器:ISP 是互聯(lián)網(wǎng)服務(wù)提供商(Internet Service Provider)的簡稱,ISP 有專門的 DNS 服務(wù)器應(yīng)對 DNS 查詢請求。

          • 根服務(wù)器:ISP 的 DNS 服務(wù)器還找不到的話,它就會向根服務(wù)器發(fā)出請求,進(jìn)行遞歸查詢(DNS 服務(wù)器先問根域名服務(wù)器.com 域名服務(wù)器的 IP 地址,然后再問 .baidu 域名服務(wù)器,依次類推)

          TCP 連接建立與斷開

          通過域名解析出 IP 地址以后就要建立 TCP/IP 連接了。

          TCP/IP 分為四層,每一層都會加上一個(gè)頭部再發(fā)送給下一層。到了接收方后,對應(yīng)的每一層則把對應(yīng)層的頭部解析拆除,丟上上一層,跟發(fā)送端的過程反過來。

          TCP/IP四層模型

          1、應(yīng)用層:發(fā)送 HTTP 請求

          瀏覽器從地址欄得到服務(wù)器 IP,接著構(gòu)造一個(gè) HTTP 報(bào)文,其中包括:

          • 請求行包含請求方法、URL、協(xié)議版本

          • 請求報(bào)頭(Request Header):由 “關(guān)鍵字: 值”對組成,每行一對,關(guān)鍵字與值使用英文 “:” 分割

          • 請求體:請求參數(shù),并不是所有的請求有又請求參數(shù)。一般 get 參數(shù) 的格式 name=tom&password=1234&realName=tomson,也可以將參數(shù)放在 body 里面。

          2、傳輸層:TCP 傳輸報(bào)文

          在傳輸報(bào)文之前會先建立 TCP/IP 連接,也就是后面我們要說的三次握手。

          在這一層解決了數(shù)據(jù)可靠傳輸、及流量控制、擁塞控制。

          可靠傳輸

          對于發(fā)送方發(fā)送的數(shù)據(jù),接收方在接受到數(shù)據(jù)之后必須要給予確認(rèn),確認(rèn)它收到了數(shù)據(jù)。如果在規(guī)定時(shí)間內(nèi),沒有給予確認(rèn)則意味著接收方?jīng)]有接受到數(shù)據(jù),然后發(fā)送方對數(shù)據(jù)進(jìn)行重發(fā)。

          TCP的可靠傳輸是通過確認(rèn)和超時(shí)重傳的機(jī)制來實(shí)現(xiàn)的,而確認(rèn)和超時(shí)重傳的具體的實(shí)現(xiàn)是通過以字節(jié)為單位的滑動(dòng)窗口機(jī)制來完成。

          TCP擁塞控制

          TCP協(xié)議通過慢啟動(dòng)機(jī)制、擁塞避免機(jī)制、加速遞減機(jī)制、快重傳和快恢復(fù)機(jī)制來共同實(shí)現(xiàn)擁塞控制。

          流量控制

          采用通知窗口實(shí)現(xiàn)對發(fā)送端的流量控制,通知窗口大小的單位是字節(jié)。TCP通過在TCP數(shù)據(jù)段首部的窗口字段中填入當(dāng)前設(shè)定的接收窗口(即通知窗口)的大小,用來告知對方 '我方當(dāng)前的接收窗口大小',以實(shí)現(xiàn)流量控制。

          通信雙方的發(fā)送窗口大小由雙方在連接建立的時(shí)候商定,在通信過程,雙方可以動(dòng)態(tài)地根據(jù)自己的情況調(diào)整對方的發(fā)送窗口大小。

          3、網(wǎng)絡(luò)層:IP 協(xié)議查詢 MAC 地址

          將數(shù)據(jù)段打包,并加入源及目標(biāo)的 IP 地址,并且負(fù)責(zé)尋找傳輸路線。判斷目標(biāo)地址是否與當(dāng)前地址處于同一網(wǎng)絡(luò)中,是的話直接根據(jù) Mac 地址發(fā)送,否則使用路由表查找下一跳地址,以及使用 ARP 協(xié)議查詢它的 Mac 地址。

          4、鏈路層:以太網(wǎng)協(xié)議

          根據(jù)以太網(wǎng)協(xié)議將數(shù)據(jù)分為以“幀”為單位的數(shù)據(jù)包,每一幀分為兩個(gè)部分:

          • 標(biāo)頭:數(shù)據(jù)包的發(fā)送者、接受者、數(shù)據(jù)類型

          • 數(shù)據(jù):數(shù)據(jù)包具體內(nèi)容

          5、Mac 地址

          以太網(wǎng)規(guī)定了連入網(wǎng)絡(luò)的所有設(shè)備都必須具備“網(wǎng)卡”接口,數(shù)據(jù)包都是從一塊網(wǎng)卡傳遞到另一塊網(wǎng)卡,網(wǎng)卡的地址就是 Mac 地址。每一個(gè) Mac 地址都是獨(dú)一無二的,具備了一對一的能力。

          6、三次握手

          在傳輸層傳輸數(shù)據(jù)之前需要建立連接,也就是三次握手創(chuàng)建可靠連接。

          三次握手

          首先建立鏈接前需要 Server 端先監(jiān)聽端口,因此 Server 端建立鏈接前的初始狀態(tài)就是 LISTEN 狀態(tài),這時(shí) Client 端準(zhǔn)備建立鏈接,先發(fā)送一個(gè) SYN 同步包,發(fā)送完同步包后,Client 端的鏈接狀態(tài)變成了 SYN_SENT 狀態(tài)。Server 端收到 SYN 后,同意建立鏈接,會向 Client 端回復(fù)一個(gè) ACK。

          由于 TCP 是雙工傳輸,Server 端也會同時(shí)向 Client 端發(fā)送一個(gè) SYN,申請 Server 向 Client 方向建立鏈接。發(fā)送完 ACK 和 SYN 后,Server 端的鏈接狀態(tài)就變成了 SYN_RCVD。

          Client 收到 Server 的 ACK 后,Client 端的鏈接狀態(tài)就變成了 ESTABLISHED 狀態(tài),同時(shí),Client 向 Server 端發(fā)送 ACK,回復(fù) Server 端的 SYN 請求。

          Server 端收到 Client 端的 ACK 后,Server 端的鏈接狀態(tài)也就變成了的 ESTABLISHED 狀態(tài),此時(shí)建連完成,雙方隨時(shí)可以進(jìn)行數(shù)據(jù)傳輸。

          在面試時(shí)需要明白三次握手是為了建立雙向的鏈接,需要記住 Client 端和 Server 端的鏈接狀態(tài)變化。另外回答建連的問題時(shí),可以提到 SYN 洪水攻擊發(fā)生的原因,就是 Server 端收到 Client 端的 SYN 請求后,發(fā)送了 ACK 和 SYN,但是 Client 端不進(jìn)行回復(fù),導(dǎo)致 Server 端大量的鏈接處在 SYN_RCVD 狀態(tài),進(jìn)而影響其他正常請求的建連。可以設(shè)置 tcp_synack_retries=0 加快半鏈接的回收速度,或者調(diào)大 tcp_max_syn_backlog 來應(yīng)對少量的 SYN 洪水攻擊。

          7、四次揮手

          我們只要關(guān)注 80 端口與 13743 端口建立的連接斷開過程,瀏覽器通過 13747 端口發(fā)送 [FIN, ACK] 這里是不是跟很多網(wǎng)上看到的不一樣?

          1. 其實(shí)是客戶端在發(fā)送 [FIN] 報(bào)文的時(shí)候順帶發(fā)了一個(gè) [ACK] 確認(rèn)上次傳輸確認(rèn)。

          2. 接著服務(wù)端通過 80 端口響應(yīng)了 [ACK] ,然后立馬響應(yīng) [FIN, ACK] 表示數(shù)據(jù)傳輸完了,可以關(guān)閉連接。

          3. 最后瀏覽器通過 13743 端口 發(fā)送 [ACK] 包給服務(wù)端,客服端與服務(wù)端連接就關(guān)閉了。

          具體流程如下圖抓包所示:

          四次揮手

          三次握手與四次揮手

          TCP 連接與斷開

          客戶端:

          • SYN_SENT - 客戶端發(fā)起第 1 次握手后,連接狀態(tài)為 SYN_SENT ,等待服務(wù)端內(nèi)核進(jìn)行應(yīng)答,如果服務(wù)端來不及處理(例如服務(wù)端的 backlog 隊(duì)列已滿)就可以看到這種狀態(tài)的連接。

          • ESTABLISHED - 表示連接處于正常狀態(tài),可以進(jìn)行數(shù)據(jù)傳送。客戶端收到服務(wù)器回復(fù)的 SYN+ACK 后,對服務(wù)端的 SYN 單獨(dú)回復(fù)(第 3 次握手),連接建立完成,進(jìn)入 ESTABLISHED 狀態(tài)。服務(wù)端程序收到第 3 次握手包后,也進(jìn)入 ESTABLISHED 狀態(tài)。

          • FIN_WAIT_1 - 客戶端發(fā)送了關(guān)閉連接的 FIN 報(bào)文后,等待服務(wù)端回復(fù) ACK 確認(rèn)。

          • FIN_WAIT_2 - 表示我方已關(guān)閉連接,正在等待服務(wù)端關(guān)閉。客戶端發(fā)了關(guān)閉連接的 FIN 報(bào)文后,服務(wù)器發(fā)回 ACK 應(yīng)答,但是沒進(jìn)行關(guān)閉,就會處于這種狀態(tài)。

          • TIME_WAIT - 雙方都正常關(guān)閉連接后,客戶端會維持 TIME_WAIT 一段時(shí)間,以確保最后一個(gè) ACK 能成功發(fā)送到服務(wù)器端。停留時(shí)長為 2 倍的 MSL (報(bào)文最大生存時(shí)間),Linux 下大約是 60 秒。所以在一個(gè)頻繁建立短連接的服務(wù)器上通常可以看到成千上萬的 TIME_WAIT 連接。

          服務(wù)端:

          • LISTEN - 表示當(dāng)前程序正在監(jiān)聽某個(gè)端口時(shí)。

          • SYN_RCVD - 服務(wù)端收到第 1 次握手后,進(jìn)入 SYN_RCVD 狀態(tài),并回復(fù)一個(gè) SYN+ACK(第 2 次握手),再等待對方確認(rèn)。

          • ESTABLISHED - 表示連接處于正常狀態(tài),可以進(jìn)行數(shù)據(jù)傳送。完成 TCP3 次握手后,連接建立完成,進(jìn)入 ESTABLISHED 狀態(tài)。

          • CLOSE_WAIT - 表示客戶端已經(jīng)關(guān)閉連接,但是本地還沒關(guān)閉,正在等待本地關(guān)閉。有時(shí)客戶端程序已經(jīng)退出了,但服務(wù)端程序由于異常或 BUG 沒有調(diào)用 close函數(shù)對連接進(jìn)行關(guān)閉,那在服務(wù)器這個(gè)連接就會一直處于 CLOSE_WAIT 狀態(tài),而在客戶機(jī)已經(jīng)不存在這個(gè)連接了。

          • LAST_ACK - 表示正在等待客戶端對服務(wù)端的關(guān)閉請求進(jìn)行最終確認(rèn)。

          TIME_WAIT 狀態(tài)存在的理由:

          劃重點(diǎn)了

          • 可靠地實(shí)現(xiàn) TCP 全雙工連接的終止 在進(jìn)行關(guān)閉連接四路握手協(xié)議時(shí),最后的 ACK 是由主動(dòng)關(guān)閉端發(fā)出的,如果這個(gè)最終的 ACK 丟失,服務(wù)器將重發(fā)最終的 FIN,因此客戶端必須維護(hù)狀態(tài)信息允 許它重發(fā)最終的 ACK。如 果不維持這個(gè)狀態(tài)信息,那么客戶端將響應(yīng) RST 分節(jié),服務(wù)器將此分節(jié)解釋成一個(gè)錯(cuò)誤( 在 java 中會拋出 connection reset 的 SocketException)。因而,要實(shí)現(xiàn) TCP 全雙工連接的正常終 止,必須處理終止序列四個(gè)分節(jié)中任何一個(gè)分節(jié)的丟失情況,主動(dòng)關(guān)閉 的客戶端必須維持狀 態(tài)信息進(jìn)入 TIME_WAIT 狀態(tài)。

          • 允許老的重復(fù)分節(jié)在網(wǎng)絡(luò)中消逝 TCP 分節(jié)可能由于路由器異常而“迷途”,在迷途期間,TCP 發(fā)送端可能因確認(rèn)超時(shí)而重發(fā)這個(gè) 分節(jié),迷途的分節(jié)在路由器修復(fù)后也會被送到最終目的地,這個(gè) 原來的迷途分節(jié)就稱為 lost duplicate。在關(guān)閉一個(gè) TCP 連接后,馬上又重新建立起一個(gè)相同的 IP 地址和端口之間的 TCP 連接,后一個(gè)連接被稱為前一個(gè)連接的化身 ( incarnation),那么有可能出現(xiàn)這種情況,前一 個(gè)連接的迷途重復(fù)分組在前一個(gè)連接終止后出現(xiàn),從而被誤解成從屬于新的化身。為了避免 這個(gè)情 況,TCP 不允許處于 TIME_WAIT 狀態(tài)的連接啟動(dòng)一個(gè)新的化身,因?yàn)?TIME_WAIT 狀 態(tài)持續(xù) 2MSL,就可以保證當(dāng)成功建立一個(gè) TCP 連接的時(shí) 候,來自連接先前化身的重復(fù)分組已 經(jīng)在網(wǎng)絡(luò)中消逝。

          另外回答斷鏈的問題時(shí),可以提到實(shí)際應(yīng)用中有可能遇到大量 Socket 處在 TIME_WAIT 或者 CLOSE_WAIT 狀態(tài)的問題。一般開啟 tcp_tw_reuse 和 tcp_tw_recycle 能夠加快 TIME-WAIT 的 Sockets 回收;而大量 CLOSE_WAIT 可能是被動(dòng)關(guān)閉的一方存在代碼 bug,沒有正確關(guān)閉鏈接導(dǎo)致的。

          簡單地說就是

          1. 保證 TCP 協(xié)議的全雙工連接能夠可靠關(guān)閉;

          2. 保證這次連接的重復(fù)數(shù)據(jù)段從網(wǎng)絡(luò)中消失,防止端口被重用時(shí)可能產(chǎn)生數(shù)據(jù)混淆;

          服務(wù)器處理請求并響應(yīng) HTTP 報(bào)文

          深入分析下 HTTP 報(bào)文到底是什么玩意。數(shù)據(jù)傳輸都是通過 TCP/IP 協(xié)議負(fù)責(zé)底層的傳輸工作, HTTP 協(xié)議基本不用操心,所謂的 “超文本傳輸協(xié)議” 似乎不怎么例會 “傳輸” 這個(gè)事情,那 HTTP 的核心又是什么呢?

          比圖 TCP 報(bào)文,它在實(shí)際要傳輸?shù)臄?shù)據(jù)之前附加了一個(gè) 20 字節(jié)的頭部數(shù)據(jù),存儲 TCP 協(xié)議必須的額外信息,例如發(fā)送方的端口號、接收方的端口號、包序號、標(biāo)志位等等。

          有了這個(gè)附加的 TCP 頭,數(shù)據(jù)包才能夠正確傳輸,到了目的地后把頭部去掉,就可以拿到真正的數(shù)據(jù)。這個(gè)很容易理解,設(shè)置起點(diǎn)與終點(diǎn),不同協(xié)議貼上不同的頭部,到了對應(yīng)目的地就拆下這個(gè)頭部,提取真正的數(shù)據(jù)。

          HTTP報(bào)文

          與 TCP/UDP 類似需要在傳輸數(shù)據(jù)前設(shè)置一些請求頭,不同的是 HTTP 是一個(gè) “純文本” 的協(xié)議,所有的頭都是 ASCII 碼的文本,很容易看出來是什么。

          再者就是他的請求報(bào)文與響應(yīng)報(bào)文的結(jié)構(gòu)基本一樣,主要三大部分組成:

          1. 起始行(Start Line):描述請求或者響應(yīng)的基本信息。

          2. Header:使用 key-value 的形式詳細(xì)說明報(bào)文信息。

          3. 空行。

          4. 消息正文(Entity):傳輸?shù)臄?shù)據(jù),圖片、視頻、文本等都可以。

          這其中前兩部分起始行和頭部字段經(jīng)常又合稱為“請求頭”或“響應(yīng)頭”,消息正文又稱為“實(shí)體”,但與“header”對應(yīng),很多時(shí)候就直接稱為“body”。

          敲黑板了

          HTTP 協(xié)議規(guī)定報(bào)文必須包含 Header,而且之后必須有一個(gè) “空行”,也就是“CRLF”,十六進(jìn)制的“0D0A”,可以沒有 “body”。

          報(bào)文結(jié)構(gòu)如下圖所示:

          HTTP報(bào)文

          截取一段報(bào)文:

          透視HTTP協(xié)議

          請求頭-起始行

          請求行由請求方法字段、URL 字段和 HTTP 協(xié)議版本字段 3 個(gè)字段組成,它們用空格分隔。例如,GET / HTTP/1.1。

          HTTP 協(xié)議的請求方法有 GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。

          GET 是請求方法, “/” 是請求的目標(biāo)資源,“HTTP/1.1” 請求協(xié)議版本號。

          GET / HTTP/1.1 翻譯成文字大概就是:“hello,服務(wù)器,我要請求根目錄下的默認(rèn)文件使用的是 HTTP 1.1 協(xié)議版本”。

          頭部 Header

          第二部分就是 Header,組成形式是 key:value,使用自定義頭需要注意事項(xiàng):

          1. header 字段不區(qū)分大小寫,通常是首字母大寫;

          2. 字段名不允許有空格,可以使用 “-”,不能使用 “_”;

          3. 字段名必須緊接著 “:”,不能有空格,但是 “:” 后面可以有空格。

          4. 字段名順序沒有意義;

          瀏覽器接收響應(yīng)并渲染數(shù)據(jù)

          接收到響應(yīng)文本 HTML,則開始執(zhí)行瀏覽器渲染機(jī)制。

          不同的瀏覽器渲染可能有所差異,但是基本按照以下步驟執(zhí)行:

          1. 根據(jù) HTML 解析 DOM 樹;

          2. 根據(jù) CSS 解析出 CSS 規(guī)則樹;

          3. 結(jié)合 DOM 樹與 CSS 規(guī)則樹,生成渲染樹;

          4. 根據(jù)生成的渲染樹計(jì)算每個(gè)節(jié)點(diǎn)的信息;

          5. 根據(jù)節(jié)點(diǎn)信息繪制畫面展示給用戶。

          點(diǎn)分享


          主站蜘蛛池模板: 国产裸体舞一区二区三区| 久久久久人妻精品一区| 日韩精品人妻av一区二区三区| 伊人色综合视频一区二区三区| 色婷婷av一区二区三区仙踪林| 秋霞日韩一区二区三区在线观看| 精品国产一区二区三区香蕉事| 国产AV国片精品一区二区| 另类一区二区三区| 波多野结衣一区二区三区高清在线| 日本一区二区三区中文字幕| 无码人妻一区二区三区免费手机| 国产av一区二区精品久久凹凸| 国产成人AV一区二区三区无码 | 亚洲一区二区在线免费观看| 国产成人av一区二区三区在线观看| 亚洲综合av永久无码精品一区二区| 亚洲性色精品一区二区在线| 一区二区视频在线观看| 天堂不卡一区二区视频在线观看| 国产亚洲无线码一区二区| 国产精品亚洲一区二区无码 | 成人免费一区二区三区| 亚洲欧美日韩国产精品一区| 国产精品无码一区二区三区电影| 国模视频一区二区| 国产精品一区二区三区久久| 日韩精品一区二区三区中文3d| 国产伦精品一区二区三区不卡| 韩国一区二区视频| 日韩在线一区视频| 又紧又大又爽精品一区二区| 真实国产乱子伦精品一区二区三区| 国产亚洲日韩一区二区三区 | 中字幕一区二区三区乱码 | 久久国产精品一区免费下载| 亚洲午夜福利AV一区二区无码| 一区二区三区在线|欧| 五十路熟女人妻一区二区| 国产精品亚洲一区二区麻豆 | 一区免费在线观看|