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
幾天有個(gè)學(xué)妹問我為什么在瀏覽器里面輸了網(wǎng)址就會顯示出來頁面,雖然這個(gè)現(xiàn)象很常見,但是要想解釋清楚確實(shí)有些小困難,當(dāng)時(shí)也只是簡單的回答了她,現(xiàn)在想趁著這個(gè)機(jī)會好好整理下相關(guān)知識。整理完才覺得其實(shí)就和我們?nèi)ヒ粋€(gè)地方找人是一個(gè)道理。所以說藝術(shù)源于生活卻又高于生活,技術(shù)同樣如此。
在回答這個(gè)問題前, 我們先來了解下我們平常說的那個(gè)網(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)于開一輛車(瀏覽器)去找一個(gè)地址(URL)
1. 緩存查找
如果你要出門找一個(gè)地方, 第一想法肯定是先想這個(gè)地方你有沒有去過, 你要是去過的話那就不需要問人直接過去就好了。 我們的系統(tǒng)也是這么想的。 當(dāng)你在瀏覽器中輸入了URL之后, 瀏覽器會先查看 瀏覽器緩存 中有沒有這個(gè)地址, 如果沒有那就再去 系統(tǒng)緩存, 如果系統(tǒng)緩存還沒有, 那就去路由器緩存找, 總之只要緩存中有, 就說明有這個(gè)資源, 那瀏覽器直接顯示出來就好了。
Tips: 這里說下 hosts文件 , hosts 是一個(gè)沒有擴(kuò)展名的系統(tǒng)文件, 可以用記事本等工具打開, 其作用就是將一些常用的網(wǎng)址域名與其對應(yīng)的IP地址建立一個(gè)關(guān)聯(lián)“數(shù)據(jù)庫”, 當(dāng)用戶在瀏覽器中輸入一個(gè)需要登錄的網(wǎng)址時(shí), 系統(tǒng)會首先自動(dò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ī)更改了請及時(shí)更新IP地址, 否則將不能訪問。
2. DNS 解析
如果你認(rèn)得去那個(gè)地址的路自然是最好, 那如果你根本就沒去過那咋辦? 肯定會有人說導(dǎo)航, 但并不是所有的地方都是導(dǎo)航能搜到的, 這個(gè)時(shí)候我們自然而然就會想著去問路人了。 瀏覽器也是這樣的, 如果在本地緩存中沒有找到想要的資源, 那就只能去其他網(wǎng)絡(luò)上的機(jī)器中尋找我想要的資源了。 那你怎么知道你要的資源在那臺機(jī)器上? 這時(shí), DNS就橫空出世了。
DNS(Domain Name System, 域名系統(tǒng)),DNS解析的過程就是尋找哪臺機(jī)器上有你需要資源的過程。當(dāng)你在瀏覽器中輸入一個(gè)地址時(shí), 例如 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)這個(gè)玩意了, 目的就是為了方便普通用戶去尋找網(wǎng)絡(luò)上的其他計(jì)算機(jī)。 所以 DNS 實(shí)際上充當(dāng)了一個(gè)翻譯的角色, 將網(wǎng)址翻譯成 IP 地址(就跟我想去南京大學(xué), 問路的那個(gè)人告訴我南京大學(xué)在廣州路上是一個(gè)道理)。
2.1 DNS 解析過程
DNS解析其實(shí)是一個(gè)遞歸查詢的過程:
在上述過程中, 首先在本地域名服務(wù)器中查詢 IP 地址, 如果沒有找到, 本地域名服務(wù)器會向根域名服務(wù)器發(fā)送一個(gè)請求, 如果根域名服務(wù)器也不存在該域名時(shí), 本地域名會向com頂級域名服務(wù)器發(fā)送一個(gè)請求, 依次類推下去。 直到最后找到目標(biāo)網(wǎng)址所對應(yīng)的 IP, 并將其緩存到本地, 以供下次使用。
2.2 DNS負(fù)載均衡
在講DNS負(fù)載均衡前先來看張圖片:
看到這可能就會有人犯嘀咕了, 我們不是 ping 的同一個(gè)網(wǎng)址嗎, 為啥兩次IP都不一樣啊? 其實(shí)原因很簡單, 如果每次都一樣是否說明你請求的資源都位于同一臺機(jī)器上面, 那么這臺機(jī)器需要多高的性能和儲存才能滿足億萬請求呢? 其實(shí)真實(shí)的互聯(lián)網(wǎng)世界背后存在成千上百臺服務(wù)器, 大型的網(wǎng)站甚至更多。 但是在用戶的眼中, 它需要的只是處理他的請求, 哪臺機(jī)器處理請求并不重要。 DNS可以返回一個(gè)合適的機(jī)器的IP給用戶, 例如可以根據(jù)每臺機(jī)器的負(fù)載量, 該機(jī)器離用戶地理位置的距離等等, 這種過程就是DNS負(fù)載均衡, 又叫做DNS重定向。
再來舉個(gè)例子, 如果你在新街口用地圖搜南京大學(xué), 返回給你的第一條數(shù)據(jù)可能就是南京大學(xué)鼓樓校區(qū)(因?yàn)榫嚯x最近), 但如果你是在仙林用地圖搜南京大學(xué), 返回給你的第一條數(shù)據(jù)就有可能是南京大學(xué)仙林校區(qū)了。 DNS負(fù)載均衡簡單來說也是這個(gè)道理。
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污染, 這里只說一個(gè)方法就是修改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:客戶端不一定特指瀏覽器, 有時(shí)候也可使用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 連接建立的時(shí)間。
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)行渲染呢? 通常是下面五個(gè)步驟:
不過這五個(gè)步驟在不同內(nèi)核的瀏覽器中執(zhí)行細(xì)節(jié)是不同的, 想深入了解的可以查閱相關(guān)資料, 這里推薦一篇文章:《瀏覽器渲染頁面過程與頁面優(yōu)化》(https://segmentfault.com/a/1190000010298038)
瀏覽器是一個(gè)邊解析邊渲染的過程。 首先瀏覽器解析HTML文件構(gòu)建DOM樹, 然后解析CSS文件構(gòu)建渲染樹, 等到渲染樹構(gòu)建完成后, 瀏覽器開始布局渲染樹并將其繪制到屏幕上。
JS的解析是由瀏覽器中的 JS 解析引擎完成的。 JS是單線程運(yùn)行, 也就是說, 在同一個(gè)時(shí)間內(nèi)只能做一件事, 所有的任務(wù)都需要排隊(duì), 前一個(gè)任務(wù)結(jié)束, 后一個(gè)任務(wù)才能開始。 但是又存在某些任務(wù)比較耗時(shí), 如IO讀寫等, 所以需要一種機(jī)制可以先執(zhí)行排在后面的任務(wù), 這就是: 同步任務(wù)(synchronous)和異步任務(wù)(asynchronous)。 JS的執(zhí)行機(jī)制就可以看做是一個(gè)主線程加上一個(gè)任務(wù)隊(duì)列(task queue)。 同步任務(wù)就是放在主線程上執(zhí)行的任務(wù), 異步任務(wù)是放在任務(wù)隊(duì)列中的任務(wù)。 所有的同步任務(wù)在主線程上執(zhí)行, 形成一個(gè)執(zhí)行棧; 異步任務(wù)有了運(yùn)行結(jié)果就會在任務(wù)隊(duì)列中放置一個(gè)事件; 腳本運(yùn)行時(shí)先依次運(yùn)行執(zhí)行棧, 然后會從任務(wù)隊(duì)列里提取事件, 運(yùn)行任務(wù)隊(duì)列中的任務(wù), 這個(gè)過程是不斷重復(fù)的, 所以又叫做事件循環(huán)(Event loop)。 如下圖所示:
7. 總結(jié)
當(dāng)上述步驟執(zhí)行完成后我們便可在瀏覽器中看到一個(gè)完整的頁面了, 總結(jié)下其實(shí)就只有幾步:
其實(shí)簡單來看這幾個(gè)過程并不是很復(fù)雜, 但是每個(gè)步驟都可以深挖出一大堆的知識, 比如DNS的優(yōu)化、頁面渲染的優(yōu)化、 HTTPS等等非常多的東西, 這里考慮到篇幅以及科普效果很多東西都一筆帶過了
Java識堂,一個(gè)高原創(chuàng),高收藏,有干貨的微信公眾號,一起成長,一起進(jìn)步,歡迎關(guān)注
如果網(wǎng)頁中有框架,那么可以通過以下幾種方式來訪問:
框架有parent及top兩個(gè)屬性
self與window是相同的
由于不同瀏覽器支持的屬性不同,所以做了一個(gè)表格方便查看。
以下是跨瀏覽器的代碼,即無論是哪種瀏覽器,都可以正常使用(注:因書本是2012年的,現(xiàn)在可能已經(jīng)不一樣了)。
var leftPos=(typeof window.screenLeft=="number") ? window.screenLeft : window.screenX;
var topPos=(typeof window.screenTop=="number") ? window.screenTop : window.screenY;
alert(leftPos);
alert(topPos);
移動(dòng)窗口(沒有實(shí)現(xiàn),不知是不是現(xiàn)在瀏覽器對這些命令有限制)
起來體驗(yàn)騰訊位置服務(wù)功能吧】
結(jié)合自己小程序業(yè)務(wù),集成騰訊位置服務(wù)地圖功能還是不錯(cuò)的,推薦各位同行提前體驗(yàn)和使用
【前言】
第一次使用騰訊位置服務(wù)也算是挺早的,當(dāng)時(shí)是在web端使用。后來,個(gè)人慢慢接觸到小程序,有一次的需求是能夠展示附近的各類店鋪,方便自己快速定位周圍有什么好吃好逛的地方。再后來每次到一個(gè)地方旅游,我們必不可少的一個(gè)需求就是需要上WC,當(dāng)時(shí)就在想如何通過一個(gè)地圖來實(shí)現(xiàn)快速定位周邊WC的位置以及步行路線,鑒于那時(shí)還沒太了解小程序里也開始集成了騰訊位置服務(wù),所以僅僅是一個(gè)想法和構(gòu)思,現(xiàn)在好了,有騰訊位置服務(wù)功能可以直接在小程序上面直接使用,借助巨人的力量可以好好發(fā)揮去實(shí)現(xiàn)需求功能了。
因此,寫這篇文章,也是希望能夠總結(jié)對接騰訊位置服務(wù)功能步驟和知識點(diǎn),方便開發(fā)同行快速上手和使用。
【申請Key】
創(chuàng)建用于自己某一業(yè)務(wù)或某一場景的Key密鑰,擁有這把鑰匙,就可以開始地圖功能體驗(yàn)啦!直接微信掃碼授權(quán)登錄即可,騰訊列表功能使用微信掃碼登錄方便好多,省去了古老需要密碼登錄的好方式。
后臺點(diǎn)擊菜單
key與配額 ->key管理,具體開發(fā)者密鑰申請信息填寫如下
【設(shè)置域名】
小程序管理后臺 -> 開發(fā) -> 開發(fā)管理 -> 開發(fā)設(shè)置 -> “服務(wù)器域名” 中設(shè)置request合法域名,添加https://apis.map.qq.com
【引入js】
下載地址:https://lbs.qq.com/miniProgram/jsSdk/jsSdkGuide/jsSdkOverview
JavaScriptSDK v1.2
// 引入SDK核心類,js文件根據(jù)自己業(yè)務(wù),位置可自行放置
var QQMapWX=require('../../libs/qqmap-wx-jssdk.js');
var qqmapsdk;
Page({
data:{
longitude:'113.390451',
latitude:'23.048914',
markers:[{longitude:'113.390451',latitude:'23.048914'}]
},
onLoad: function () {
// 實(shí)例化API核心類
qqmapsdk=new QQMapWX({
key: 'xxxx-xxxx,你自己申請到的key'
});
},
onShow: function () {
// 調(diào)用接口
qqmapsdk.search({
keyword: '廣州大學(xué)城',
success: function (res) {
//console.log(res);
},
fail: function (res) {
//console.log(res);
},
complete: function (res) {
console.log(res);
}
});
}
})
view代碼
<view class='view'>
<map longitude="{{longitude}}" latitude="{{latitude}}" markers="{{markers}}"></map>
</view>
【標(biāo)注顯示文本】
js代碼效果
//關(guān)鍵代碼
//markers屬性下還有屬性成員-{label:{content:'廣州番禺大學(xué)城'}
data:{
markers:[{label:{content:'廣州番禺大學(xué)城'},longitude:'113.390451',latitude:'23.048914'}]
},
【W(wǎng)C路線規(guī)劃】
下面的還有做樣式設(shè)置,比如:箭頭、和線路顏色,以及起點(diǎn)和終點(diǎn)的文本顯示等等,純屬默認(rèn)參數(shù)
效果
// 引入SDK核心類,js文件根據(jù)自己業(yè)務(wù),位置可自行放置
var QQMapWX=require('../../libs/qqmap-wx-jssdk.js');
var qqmapsdk;
Page({
data:{
longitude:'113.390451',
latitude:'23.048914',
markers:[{label:{content:'廣州番禺大學(xué)城'},longitude:'113.390451',latitude:'23.048914'}]
},
onLoad: function () {
// 實(shí)例化API核心類
qqmapsdk=new QQMapWX({
key: 'xxxx-xxxx,你自己申請到的key'
});
},
onShow: function () {
// 調(diào)用接口
qqmapsdk.search({
keyword: 'GoGo廁所',
success: function (res) {
//console.log(res);
},
fail: function (res) {
//console.log(res);
},
complete: function (res) {
console.log(res);
}
});
},
//觸發(fā)表單提交事件,調(diào)用接口
formSubmit(e) {
//起點(diǎn)坐標(biāo):23.048914,113.390451
//終點(diǎn)坐標(biāo):23.061793,113.392056
//23.061793,113.392056
//23.063073,113.391762
var _this=this;
//調(diào)用距離計(jì)算接口
qqmapsdk.direction({
mode: 'driving',//可選值:'driving'(駕車)、'walking'(步行)、'bicycling'(騎行),不填默認(rèn):'driving',可不填
//from參數(shù)不填默認(rèn)當(dāng)前地址
from: e.detail.value.start,
to: e.detail.value.dest,
success: function (res) {
console.log(res);
var ret=res;
var coors=ret.result.routes[0].polyline, pl=[];
//坐標(biāo)解壓(返回的點(diǎn)串坐標(biāo),通過前向差分進(jìn)行壓縮)
var kr=1000000;
for (var i=2; i < coors.length; i++) {
coors[i]=Number(coors[i - 2]) + Number(coors[i]) / kr;
}
//將解壓后的坐標(biāo)放入點(diǎn)串?dāng)?shù)組pl中
for (var i=0; i < coors.length; i +=2) {
pl.push({ latitude: coors[i], longitude: coors[i + 1] })
}
console.log(pl)
//設(shè)置polyline屬性,將路線顯示出來,將解壓坐標(biāo)第一個(gè)數(shù)據(jù)作為起點(diǎn)
_this.setData({
latitude:pl[0].latitude,
longitude:pl[0].longitude,
polyline: [{
points: pl,
color: '#FF0000DD',
width: 4
}]
})
},
fail: function (error) {
console.log(error);
},
complete: function (res) {
console.log(res);
}
});
}
})
<!--地圖容器-->
<map
id="myMap"
style="width: 100%; height: 300px;"
longitude="{{longitude}}" latitude="{{latitude}}"
scale='16'
polyline="{{polyline}}"
show-location
>
</map>
<form bindsubmit="formSubmit">
<!--輸入起點(diǎn)和目的地經(jīng)緯度坐標(biāo),格式為string格式-->
<!--起點(diǎn)輸入框,同終點(diǎn),不填默認(rèn)當(dāng)前位置-->
<label>起點(diǎn)坐標(biāo):<input style="border:1px solid #000;" name="start"></input></label>
<!--終點(diǎn)輸入框,例:39.984060,116.307520-->
<label>終點(diǎn)坐標(biāo):<input style="border:1px solid #000;" name="dest"></input></label>
<!--提交表單數(shù)據(jù)-->
<button form-type="submit">路線規(guī)劃</button>
</form>
【開啟個(gè)性化騰訊地圖】
微信掃碼綁定,微信會判斷當(dāng)前小程序是否注冊騰訊位置服務(wù),如果提示未注冊,那么可以輸入已注冊的賬號,一般是手機(jī)號碼登錄,完成小程序和騰訊位置服務(wù)賬號的綁定。
有些插件還要另外申請appid
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。