Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 亚洲精品国产第七页在线,最近日本中文字幕免费完整,免费jizz在在线播放国产

          整合營銷服務(wù)商

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

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

          JavaScript 檢測瀏覽器和操作系統(tǒng)

          JavaScript 檢測瀏覽器和操作系統(tǒng)

          斷瀏覽器的方法:

          第一種方法:

          <script type="text/javascript">
          var Sys={};
          var ua=navigator.userAgent.toLowerCase();
          var s;
          (s=ua.match(/msie ([\d.]+)/)) ? Sys.ie=s[1] :
          (s=ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox=s[1] :
          (s=ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome=s[1] :
          (s=ua.match(/opera.([\d.]+)/)) ? Sys.opera=s[1] :
          (s=ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari=s[1] : 0;
          //以下進(jìn)行測試
          if (Sys.ie) document.write('IE: ' + Sys.ie);
          if (Sys.firefox) document.write('Firefox: ' + Sys.firefox);
          if (Sys.chrome) document.write('Chrome: ' + Sys.chrome);
          if (Sys.opera) document.write('Opera: ' + Sys.opera);
          if (Sys.safari) document.write('Safari: ' + Sys.safari);
          </script>


          第二種方法:

          在開篇

          什么是表單呢?當(dāng)前端想要提交數(shù)據(jù)給后端,怎么搞?那么在前端開發(fā)中,表單是常用的手段,比如常見的場景有:登錄框、賬號注冊頁、主機(jī)信息錄入CMDB等等場景都是需要表單。那么在本篇中,筆者除了講一些基本的知識點(diǎn),還會再結(jié)合后端的方式來演示如何接收表單提交的數(shù)據(jù)。希望這些小小的演示可以起到拋磚引玉的效果。

          盤點(diǎn)HTML表單基礎(chǔ)

          1. from元素

          構(gòu)建表單,主要是通過from元素,我們先來一個最簡單的小栗子,看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機(jī)信息錄入CMDB</h3>
                  <form>
                      <label for="hostname">主機(jī)名:</label><br>
                      <input type="text" id="hostname" name="hostname"><br>
                      <label for="ipaddr">IP地址:</label><br>
                      <input type="text" id="ipaddr" name="ipaddr"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          通上面的小栗子可以知道,form表單的主要通途是用于收集用戶的輸入。在from表單里面,還包含著各種不同類型的input元素,比如我們上面小栗子中用到的文本(text)、提交按鈕(submit)。

          input元素是表單里最重要的元素,它有很多type屬性,下面我們來總結(jié)下:

          類型描述text文本輸入radio單選按鈕checkbox提交按鈕submit提交按鈕button可單擊按鈕

          在上面小栗子中,除了input元素之外,不知道大家注意label元素沒有。label元素的主要用途是為input元素定義標(biāo)簽,且用for屬性和input元素的id屬性進(jìn)行綁定呢。

          2. 單選按鈕

          什么是單選按鈕?就是在多個選項(xiàng)中,你只能選其中1個,不能多選。下面我們看個小栗子,看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>問答題1(單選):某站長,工作經(jīng)驗(yàn)不足1年,僅從互聯(lián)網(wǎng)收集學(xué)習(xí)資料制定學(xué)習(xí)路線售賣盈利,從道德層面角度分析是否有問題?</h3>
                  <form>
                      <input type="radio" id="i1" name="problem" value="yes">
                      <label for="i1">有</label>
                      <input type="radio" id="i2" name="problem" value="no">
                      <label for="i2">沒有</label>
                      <input type="radio" id="i3" name="problem" value="not_clear">
                      <label for="i3">不清楚</label>
                  </form>
                  <h3>問答題2(單選):實(shí)際工作經(jīng)驗(yàn)不足1年的人員折騰的學(xué)習(xí)資料您覺得是否對你有幫助?</h3>
                  <form>
                      <input type="radio" id="w1" name="problem" value="yes">
                      <label for="w1">有</label>
                      <input type="radio" id="w2" name="problem" value="no">
                      <label for="w2">沒有</label>
                      <input type="radio" id="w3" name="problem" value="not_clear">
                      <label for="w3">不清楚</label>
                  </form>
              </body>
          </html>
          

          效果如下圖:

          上面的小栗子中,出了兩道問答題,均為單選題。那么,類似的需求都是可以使用輸入類型為radio來實(shí)現(xiàn)需要使用單選按鈕的場景。

          3. 復(fù)選框

          什么是復(fù)選框?復(fù)選框就是可以選擇多個選項(xiàng),當(dāng)需要多選的時候,使用復(fù)選框輸入類型就對了。看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>問答題1(單選):某站長,工作經(jīng)驗(yàn)不足1年,僅從互聯(lián)網(wǎng)收集學(xué)習(xí)資料制定學(xué)習(xí)路線售賣盈利,從道德層面角度分析是否有問題?</h3>
                  <form>
                      <input type="checkbox" id="i1" name="problem" value="yes">
                      <label for="i1">有</label>
                      <input type="checkbox" id="i2" name="problem" value="no">
                      <label for="i2">沒有</label>
                      <input type="checkbox" id="i3" name="problem" value="not_clear">
                      <label for="i3">不清楚</label><br>
                      <input type="submit" value="提交">
                  </form>
                  <h3>問答題2(單選):實(shí)際工作經(jīng)驗(yàn)不足1年的人員折騰的學(xué)習(xí)資料您覺得是否對你有幫助?</h3>
                  <form>
                      <input type="checkbox" id="w1" name="problem" value="yes">
                      <label for="w1">有</label>
                      <input type="checkbox" id="w2" name="problem" value="no">
                      <label for="w2">沒有</label>
                      <input type="checkbox" id="w3" name="problem" value="not_clear">
                      <label for="w3">不清楚</label><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          上面的小栗子中,實(shí)現(xiàn)復(fù)選框的輸入類型是checkbox,這個是重點(diǎn)哦!

          4. 提交按鈕

          當(dāng)有數(shù)據(jù)要提交給后端的時候怎么搞?如果后端是API服務(wù),可以給它提交json。如果是前端頁面,就需要通過構(gòu)建表單來獲取用戶的輸入。基于表單提交數(shù)據(jù)給后端,怎么提交?需要一個可以點(diǎn)擊的提交按鈕,那這個按鈕怎么來?先看下面代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機(jī)信息</h3>
                  <form>
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          效果如下圖:

          輸入類型為submit,說明它就是提交按鈕,注意上面代碼type="submit"了嗎?

          HTML表單重要屬性

          1. Action屬性

          在之前的例子中,前端表單需要將數(shù)據(jù)提交給后端,除了需要一個提交按鈕外,還需要action屬性。當(dāng)點(diǎn)擊提交按鈕后,表單的數(shù)據(jù)該發(fā)到后端的哪個url進(jìn)行處理,就是定義在action屬性中。接下來,我們結(jié)合前端和后端直接來個小實(shí)戰(zhàn),后端代碼用Python的Flask框架。

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機(jī)信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼:

          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=["GET", "POST"])
          def ttropsstack():
              args=request.args
              print 'ip addr is: %s' % args.get('ip')
              return 'ok'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          前端和后端的代碼寫完后,我們接下來看看效果

          輸入IP地址后,點(diǎn)擊提交

          這個ok是后端返回的

          后端接收到數(shù)據(jù)后,啥也沒做,只是做了簡單打印

          這個小栗子很簡單,通過這個小栗子,是不是對action屬性的用法有了進(jìn)一步的理解呢?

          2. Method屬性

          method屬性的用途是指定提交數(shù)據(jù)的http方法,通常有2個,get和post。接下來我們在上個小栗子的基礎(chǔ)上做個小改造,看下面代碼

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機(jī)信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="get">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼:

          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=["POST"])
          def ttropsstack():
              args=request.args
              print 'ip addr is: %s' % args.get('ip')
              return 'ok'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          當(dāng)前端輸入數(shù)據(jù)后,提交表單時,直接告訴你這是不允許的方法

          在這個例子中,是因?yàn)榍岸说谋韱瘟酥付薽ethod為get請求,而后端接收數(shù)據(jù)的method規(guī)定了需要post請求,故所以出現(xiàn)這個問題。

          下面我們改造一下后端代碼:

          # coding: utf8
          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method=='POST':
                  print request.get_data(as_text=True)
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          前端表單中的method還是保持get請求,再次提交,后端的返回如下:

          看到了嗎?后端判斷前端過來的請求是get還是post,很顯然,前端過來的請求是get,并且返回了非常友好的提示。

          接下來我們繼續(xù)改造一下前端的代碼,將請求修改為post,代碼如下:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <h3>主機(jī)信息</h3>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="ipaddr">IP地址</label>
                      <input type="text" id="ipaddr" name="ip"><br>
                      <input type="submit" value="提交">
                  </form>
              </body>
          </html>
          

          后端代碼也稍微改造一下,改變接收前端數(shù)據(jù)的方法

          # coding: utf8
          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method=='POST':
                  a=request.form
                  print a.get('ip')
                  print type(a)
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          輸入IP地址,并點(diǎn)擊提交

          提交后,后端給前端返回了ok

          接下來看下后端,后端啥也沒做,就獲取到表單的數(shù)據(jù),然后打印了數(shù)據(jù),并且打印了下數(shù)據(jù)類型

          好了,關(guān)于前端的action屬性和Method屬性就講到這里了。為了講解action和method,還結(jié)合了后端的一丟丟知識,前端和后端的知識點(diǎn)以后都會慢慢講到哈!

          HTML表單常用元素

          1. 下拉列表

          先來個前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="opslist">運(yùn)維開發(fā)應(yīng)掌握的技能:</label>
                      <select id="opslist" name="opslist">
                          <option value="python">Python語言</option>
                          <option value="go">Go語言</option>
                          <option value="shell">Shell語言</option>
                          <option value="database">數(shù)據(jù)庫</option>
                          <option value="frontend">前端</option>
                          <option value="linux">Linux</option>
                          <option value="network">網(wǎng)絡(luò)</option>
                          <option value="storage">存儲</option>
                      </select>
                      <input type="submit">
                  </form>
              </body>
          </html>
          

          后端代碼:

          # coding: utf8
          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method=='POST':
                  a=request.form
                  print a.get('opslist')
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          在下拉框中選擇“Go語言”,并提交

          后端啥也沒干,就只做了打印

          2. 允許多選

          前端代碼:

          <!DOCTYPE html>
          <html lang="zh">
              <head>
                  <meta charset="UTF-8">
                  <title>彩虹運(yùn)維技術(shù)棧社區(qū)主頁</title>
              </head>
              <body>
                  <h2>彩虹運(yùn)維技術(shù)棧社區(qū),公眾號ID:TtrOpsStack</h2>
                  <form action="http://192.168.11.10:8088/ttropsstack" target="_blank" method="post">
                      <label for="opslist">運(yùn)維開發(fā)應(yīng)掌握的技能:</label>
                      <select id="opslist" name="opslist" size="6" multiple>
                          <option value="python">Python語言</option>
                          <option value="go">Go語言</option>
                          <option value="shell">Shell語言</option>
                          <option value="database">數(shù)據(jù)庫</option>
                          <option value="frontend">前端</option>
                          <option value="linux">Linux</option>
                          <option value="network">網(wǎng)絡(luò)</option>
                          <option value="storage">存儲</option>
                      </select>
                      <input type="submit">
                  </form>
              </body>
          </html>
          

          上述前端代碼中,是使用multiple屬性來實(shí)現(xiàn)選擇多個值。

          后端代碼的打印方式稍微做了些許調(diào)整:

          # coding: utf8
          from flask import Flask, request
          
          webapp=Flask(__name__)
          
          @webapp.route('/ttropsstack', methods=['GET','POST'])
          def ttropsstack():
              if request.method=='POST':
                  data=request.get_data()
                  print data
                  return 'ok'
              else:
                  return '提交數(shù)據(jù)需要post請求'
          
          if __name__=='__main__':
          
              webapp.run(host="0.0.0.0", port=8088, debug=True)
          

          按住ctrl或者shift鍵可進(jìn)行多選

          后端打印的效果圖下圖:

          寫在最后

          關(guān)于表單基礎(chǔ)知識點(diǎn)的講解就這么愉快的結(jié)束了,關(guān)于更多表單的元素、輸入屬性、輸入類型可自行查閱和實(shí)戰(zhàn),筆者因時間有限就不一一演示。感謝您的閱讀,望多多關(guān)注我們、點(diǎn)贊、轉(zhuǎn)發(fā)!

          本文轉(zhuǎn)載于(喜歡的盆友關(guān)注我們):https://mp.weixin.qq.com/s/L-Msv39JrF7AzRx4K1OLjA

          文公眾號來源:01二進(jìn)制 作者:雇個城管打天下

          記得在面試的時候也被問到這題,當(dāng)時答得并不好,這道題目其實(shí)可以挖掘很多的知識點(diǎn)出來,建議閱讀!

          前幾天有個學(xué)妹問我為什么在瀏覽器里面輸了網(wǎng)址就會顯示出來頁面,雖然這個現(xiàn)象很常見,但是要想解釋清楚確實(shí)有些小困難,當(dāng)時也只是簡單的回答了她,現(xiàn)在想趁著這個機(jī)會好好整理下相關(guān)知識。整理完才覺得其實(shí)就和我們?nèi)ヒ粋€地方找人是一個道理。所以說藝術(shù)源于生活卻又高于生活,技術(shù)同樣如此。

          在回答這個問題前, 我們先來了解下我們平常說的那個網(wǎng)址到底是啥?

          網(wǎng)址的學(xué)名叫做統(tǒng)一資源定位符(Uniform Resource Locator, 常縮寫為URL), 我們知道現(xiàn)在的互聯(lián)網(wǎng)其實(shí)就是由眾多資源所構(gòu)成的一張巨大的網(wǎng), 如何定位那些資源就是靠的URL, 因此我們也可以把URL理解為是網(wǎng)絡(luò)上資源的“門牌號“, 我們在瀏覽器中輸入網(wǎng)址, 就相當(dāng)于開一輛車(瀏覽器)去找一個地址(URL)

          1. 緩存查找

          如果你要出門找一個地方, 第一想法肯定是先想這個地方你有沒有去過, 你要是去過的話那就不需要問人直接過去就好了。 我們的系統(tǒng)也是這么想的。 當(dāng)你在瀏覽器中輸入了URL之后, 瀏覽器會先查看 瀏覽器緩存 中有沒有這個地址, 如果沒有那就再去 系統(tǒng)緩存, 如果系統(tǒng)緩存還沒有, 那就去路由器緩存找, 總之只要緩存中有, 就說明有這個資源, 那瀏覽器直接顯示出來就好了。

          Tips: 這里說下 hosts文件hosts 是一個沒有擴(kuò)展名的系統(tǒng)文件, 可以用記事本等工具打開, 其作用就是將一些常用的網(wǎng)址域名與其對應(yīng)的IP地址建立一個關(guān)聯(lián)“數(shù)據(jù)庫”, 當(dāng)用戶在瀏覽器中輸入一個需要登錄的網(wǎng)址時, 系統(tǒng)會首先自動從 hosts 文件中尋找對應(yīng)的 IP 地址,一旦找到, 系統(tǒng)會立即打開對應(yīng)網(wǎng)頁, 如果沒有找到, 則系統(tǒng)會再將網(wǎng)址提交 DNS 域名解析服務(wù)器進(jìn)行IP地址的解析。 需要注意的是, hosts文件配置的映射是靜態(tài)的, 如果網(wǎng)絡(luò)上的計(jì)算機(jī)更改了請及時更新IP地址, 否則將不能訪問。

          2. DNS 解析

          如果你認(rèn)得去那個地址的路自然是最好, 那如果你根本就沒去過那咋辦? 肯定會有人說導(dǎo)航, 但并不是所有的地方都是導(dǎo)航能搜到的, 這個時候我們自然而然就會想著去問路人了。 瀏覽器也是這樣的, 如果在本地緩存中沒有找到想要的資源, 那就只能去其他網(wǎng)絡(luò)上的機(jī)器中尋找我想要的資源了。 那你怎么知道你要的資源在那臺機(jī)器上? 這時, DNS就橫空出世了。

          DNS(Domain Name System, 域名系統(tǒng)),DNS解析的過程就是尋找哪臺機(jī)器上有你需要資源的過程。當(dāng)你在瀏覽器中輸入一個地址時, 例如 www.baidu.com, 其實(shí)這段URL并不是真正意義上的地址。 互聯(lián)網(wǎng)上每一臺計(jì)算機(jī)的唯一標(biāo)識是它的 IP 地址(比如127.0.0.1就是我們本機(jī)的 IP 地址), 但是 IP 地址并不方便記憶(畢竟都是很長的數(shù)字串), 所以也就出現(xiàn)了網(wǎng)址(URL)這個玩意了, 目的就是為了方便普通用戶去尋找網(wǎng)絡(luò)上的其他計(jì)算機(jī)。 所以 DNS 實(shí)際上充當(dāng)了一個翻譯的角色, 將網(wǎng)址翻譯成 IP 地址(就跟我想去南京大學(xué), 問路的那個人告訴我南京大學(xué)在廣州路上是一個道理)。

          2.1 DNS 解析過程

          DNS解析其實(shí)是一個遞歸查詢的過程:

          在上述過程中, 首先在本地域名服務(wù)器中查詢 IP 地址, 如果沒有找到, 本地域名服務(wù)器會向根域名服務(wù)器發(fā)送一個請求, 如果根域名服務(wù)器也不存在該域名時, 本地域名會向com頂級域名服務(wù)器發(fā)送一個請求, 依次類推下去。 直到最后找到目標(biāo)網(wǎng)址所對應(yīng)的 IP, 并將其緩存到本地, 以供下次使用。

          2.2 DNS負(fù)載均衡

          在講DNS負(fù)載均衡前先來看張圖片:

          看到這可能就會有人犯嘀咕了, 我們不是 ping 的同一個網(wǎng)址嗎, 為啥兩次IP都不一樣啊? 其實(shí)原因很簡單, 如果每次都一樣是否說明你請求的資源都位于同一臺機(jī)器上面, 那么這臺機(jī)器需要多高的性能和儲存才能滿足億萬請求呢? 其實(shí)真實(shí)的互聯(lián)網(wǎng)世界背后存在成千上百臺服務(wù)器, 大型的網(wǎng)站甚至更多。 但是在用戶的眼中, 它需要的只是處理他的請求, 哪臺機(jī)器處理請求并不重要。 DNS可以返回一個合適的機(jī)器的IP給用戶, 例如可以根據(jù)每臺機(jī)器的負(fù)載量, 該機(jī)器離用戶地理位置的距離等等, 這種過程就是DNS負(fù)載均衡, 又叫做DNS重定向。

          再來舉個例子, 如果你在新街口用地圖搜南京大學(xué), 返回給你的第一條數(shù)據(jù)可能就是南京大學(xué)鼓樓校區(qū)(因?yàn)榫嚯x最近), 但如果你是在仙林用地圖搜南京大學(xué), 返回給你的第一條數(shù)據(jù)就有可能是南京大學(xué)仙林校區(qū)了。 DNS負(fù)載均衡簡單來說也是這個道理。

          2.3 DNS 污染

          DNS 污染(DNS cache pollution), 又稱域名服務(wù)器緩存投毒(DNS cache poisoning), 是指一些刻意制造或無意中制造出來的域名服務(wù)器數(shù)據(jù)包, 把域名指往不正確的IP地址

          某些網(wǎng)絡(luò)運(yùn)營商為了某些目的, 對DNS進(jìn)行了某些操作, 導(dǎo)致上網(wǎng)的用戶無法通過域名取得正確的IP地址。 某些國家或地區(qū)出于某些目的為了防止某網(wǎng)站被訪問, 而且其又掌握部分國際DNS根目錄服務(wù)器或鏡像, 也會利用此方法進(jìn)行屏蔽。 (Google、 Facebook等)

          至于如果防止DNS污染, 這里只說一個方法就是修改hosts文件, 其他的自行搜索吧。

          3. TCP連接

          其實(shí)在上面DNS解析的圖中就已經(jīng)有了TCP連接的過程了:

          我們通過DNS解析獲取到了網(wǎng)址所對應(yīng)的IP地址后, 便需要發(fā)起TCP連接請求, 這里總共需要三次握手, 具體的過程就不贅述了, 可以查閱相關(guān)資料, 這里推薦劉欣老師的《TCP/IP 之 大明王朝郵差》, 以及大學(xué)計(jì)算機(jī)網(wǎng)絡(luò)課本里面的TCP相關(guān)章節(jié)。

          4. HTTP 請求

          握手成功后, 瀏覽器就可以向服務(wù)器發(fā)送http請求了, 請求數(shù)據(jù)包。 發(fā)送HTTP請求的過程就是構(gòu)建HTTP請求報(bào)文并通過TCP協(xié)議中發(fā)送到服務(wù)器指定端口(HTTP協(xié)議80/8080, HTTPS協(xié)議443)。HTTP請求報(bào)文是由三部分組成: 請求行,請求報(bào)頭和請求正文。

          4.1 請求行

          格式如下:

          Method
           
          RequestURL
           
          HTTPVersion
           CRLF
          

          例如:

          GET index
          .
          html HTTP
          /
          1.1
          

          常用的方法有: GET,POST,PUT,DELETE,OPTIONS,HEAD。

          4.2 請求報(bào)頭

          請求報(bào)頭允許客戶端向服務(wù)器傳遞請求的附加信息和客戶端自身的信息。

          Tips:客戶端不一定特指瀏覽器, 有時候也可使用Linux下的CURL命令以及HTTP客戶端測試工具等。

          常見的請求報(bào)頭有: Accept,AcceptCharset,AcceptEncoding,AcceptLanguage,ContentType,Authorization,Cookie,UserAgent等。

          上圖是使用Chrome開發(fā)者工具截取的對百度的HTTP請求以及響應(yīng)報(bào)文, 從圖中可以看出, 請求報(bào)頭中使用了Accept, AcceptEncoding, AcceptLanguage, CacheControl, Connection, Cookie等字段。 Accept 用于指定客戶端用于接受哪些類型的信息, AcceptEncoding 與 Accept 類似, 它用于指定接受的編碼方式。Connection 設(shè)置為 Keepalive 用于告訴客戶端本次 HTTP 請求結(jié)束之后并不需要關(guān)閉 TCP 連接, 這樣可以使下次 HTTP 請求使用相同的 TCP 通道, 節(jié)省 TCP 連接建立的時間。

          5. 服務(wù)器響應(yīng)

          這部分對應(yīng)的就是后端工程師眼中的 HTTP。 后端從在固定的端口接收到 TCP 報(bào)文開始, 這一部分對應(yīng)于編程語言中的 socket。 它會對 TCP 連接進(jìn)行處理, 對 HTTP 協(xié)議進(jìn)行解析, 并按照報(bào)文格式進(jìn)一步封裝成 HTTP Request對象, 供上層使用。 這一部分工作一般是由 Web 服務(wù)器去進(jìn)行, 常用的Web服務(wù)器有 Tomcat, IIS 和 Netty 等等。

          HTTP響應(yīng)報(bào)文也是由三部分組成: 狀態(tài)碼, 響應(yīng)報(bào)頭響應(yīng)報(bào)文。 篇幅原因這里就不詳細(xì)展開了。

          6. 瀏覽器解析網(wǎng)頁信息

          服務(wù)器返回給瀏覽器的文本信息, 通常是 HTML, CSS, JS, 圖片等文件, 那么瀏覽器是如何對澤瀉內(nèi)容進(jìn)行渲染呢? 通常是下面五個步驟:

          1. 處理 HTML 標(biāo)記并構(gòu)建 DOM 樹。
          2. 處理 CSS 標(biāo)記并構(gòu)建 CSSOM 樹。
          3. 將 DOM 與 CSSOM 合并成一個渲染樹。
          4. 根據(jù)渲染樹來布局, 以計(jì)算每個節(jié)點(diǎn)的幾何信息。
          5. 將各個節(jié)點(diǎn)繪制到屏幕上。

          不過這五個步驟在不同內(nèi)核的瀏覽器中執(zhí)行細(xì)節(jié)是不同的, 想深入了解的可以查閱相關(guān)資料, 這里推薦一篇文章:《瀏覽器渲染頁面過程與頁面優(yōu)化》(https://segmentfault.com/a/1190000010298038)

          瀏覽器是一個邊解析邊渲染的過程。 首先瀏覽器解析HTML文件構(gòu)建DOM樹, 然后解析CSS文件構(gòu)建渲染樹, 等到渲染樹構(gòu)建完成后, 瀏覽器開始布局渲染樹并將其繪制到屏幕上。

          JS的解析是由瀏覽器中的 JS 解析引擎完成的。 JS是單線程運(yùn)行, 也就是說, 在同一個時間內(nèi)只能做一件事, 所有的任務(wù)都需要排隊(duì), 前一個任務(wù)結(jié)束, 后一個任務(wù)才能開始。 但是又存在某些任務(wù)比較耗時, 如IO讀寫等, 所以需要一種機(jī)制可以先執(zhí)行排在后面的任務(wù), 這就是: 同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。 JS的執(zhí)行機(jī)制就可以看做是一個主線程加上一個任務(wù)隊(duì)列(task queue)。 同步任務(wù)就是放在主線程上執(zhí)行的任務(wù), 異步任務(wù)是放在任務(wù)隊(duì)列中的任務(wù)。 所有的同步任務(wù)在主線程上執(zhí)行, 形成一個執(zhí)行棧; 異步任務(wù)有了運(yùn)行結(jié)果就會在任務(wù)隊(duì)列中放置一個事件; 腳本運(yùn)行時先依次運(yùn)行執(zhí)行棧, 然后會從任務(wù)隊(duì)列里提取事件, 運(yùn)行任務(wù)隊(duì)列中的任務(wù), 這個過程是不斷重復(fù)的, 所以又叫做事件循環(huán)(Event loop)。 如下圖所示:

          7. 總結(jié)

          當(dāng)上述步驟執(zhí)行完成后我們便可在瀏覽器中看到一個完整的頁面了, 總結(jié)下其實(shí)就只有幾步:

          1. 瀏覽器地址欄輸入url
          2. 瀏覽器會先查看瀏覽器緩存系統(tǒng)緩存路由緩存, 如有存在緩存, 就直接顯示。 如果沒有, 接著第3步
          3. 域名解析(DNS)獲取相應(yīng)的 IP
          4. 瀏覽器向服務(wù)器發(fā)起 tcp 連接, 與瀏覽器建立 tcp 三次握手
          5. 握手成功, 瀏覽器向服務(wù)器發(fā)送 http 請求, 請求數(shù)據(jù)包
          6. 服務(wù)器請求數(shù)據(jù), 將數(shù)據(jù)返回到瀏覽器
          7. 瀏覽器接收響應(yīng), 讀取頁面內(nèi)容, 解析 html 源碼, 生成 Dom 樹
          8. 解析 css 樣式、 瀏覽器渲染, js交互

          其實(shí)簡單來看這幾個過程并不是很復(fù)雜, 但是每個步驟都可以深挖出一大堆的知識, 比如DNS的優(yōu)化、頁面渲染的優(yōu)化、 HTTPS等等非常多的東西, 這里考慮到篇幅以及科普效果很多東西都一筆帶過了。

          微信公眾號【程序員喬戈里】 作者喬戈里,斜杠青年,哈工大本碩985 碩士,百度Java 研發(fā)工程師,目前致力于分享求職必備學(xué)習(xí)經(jīng)驗(yàn)、求職心得和成長感悟/技術(shù)文章。(關(guān)注公眾號送9000G 考研/python/C++/java/前端/小程序/微信公眾號/機(jī)器學(xué)習(xí)/人工智能資源)


          主站蜘蛛池模板: 麻豆视频一区二区三区| 亚洲国产成人久久一区久久| 国产午夜精品一区二区三区小说 | 亚洲中文字幕一区精品自拍| 免费观看一区二区三区| 在线视频亚洲一区| 成人无码AV一区二区| 国偷自产视频一区二区久| 亚洲一区二区三区香蕉| 尤物精品视频一区二区三区| 亚洲区精品久久一区二区三区| 亚洲一区二区三区无码中文字幕 | 无码人妻精品一区二区三区在线| 色天使亚洲综合一区二区| 一区二区传媒有限公司| 少妇无码一区二区三区| 免费一区二区无码东京热| 国产一在线精品一区在线观看| 波霸影院一区二区| 一区二区三区在线观看免费| 国产日韩精品一区二区三区| 在线一区二区三区| 暖暖免费高清日本一区二区三区| 日本一区二区三区爆乳| 亚洲一区二区三区高清在线观看| 日韩精品一区二区三区老鸭窝| 少妇无码一区二区三区| 蜜桃无码一区二区三区| 精品一区二区视频在线观看 | 三上悠亚精品一区二区久久| 成人区人妻精品一区二区不卡视频 | 国产品无码一区二区三区在线| 亲子乱av一区区三区40岁| 日本一区二区三区免费高清| 国产精品视频免费一区二区| 日韩精品一区二区三区中文版 | 日韩AV无码一区二区三区不卡| 国产精品亚洲专区一区| 亚洲性日韩精品国产一区二区| 久久影院亚洲一区| 无码人妻久久久一区二区三区|