、XHTML與HTML的區別
文檔結構
XHTML DOCTYPE 是強制性的
<html>中的 XML namespace 屬性是強制性的
<html>、<head>、<title>以及 <body>也是強制性的
元素語法
XHTML 元素必須正確嵌套
XHTML 元素必須始終關閉
XHTML 元素必須小寫
XHTML 文檔必須有一個根元素
屬性語法
XHTML 屬性必須使用小寫
XHTML 屬性值必須用引號包圍
XHTML 屬性最小化也是禁止的
二、HTML5中一些新特性
用于繪畫的 canvas 元素
用于媒介回放的 video 和 audio 元素
對本地離線存儲的更好的支持
新的特殊內容元素,比如 article、footer、header、nav、section
新的表單控件,比如 calendar、date、time、email、url、search
注意:最新版本的 Safari、Chrome、Firefox 以及 Opera 支持某些 HTML5 特性。Internet Explorer 9 將支持某些 HTML5 特性。
IE9 以下版本瀏覽器兼容HTML5的方法,使用本站的靜態資源的html5shiv包:
三、HTML5web存儲
使用HTML5可以在本地存儲用戶的瀏覽數據。
早些時候,本地存儲使用的是 cookie。但是Web 存儲需要更加的安全與快速. 這些數據不會被保存在服務器上,但是這些數據只用于用戶請求網站數據上.它也可以存儲大量的數據,而不影響網站的性能.
數據以 鍵/值 對存在, web網頁的數據只允許該網頁訪問使用。
瀏覽器支持:
Internet Explorer 8+, Firefox, Opera, Chrome, 和 Safari支持Web 存儲。
注意: Internet Explorer 7 及更早IE版本不支持web 存儲.
localStorage 和 sessionStorage
客戶端存儲數據的兩個對象為:
localStorage - 用于長久保存整個網站的數據,保存的數據沒有過期時間,直到手動去除。
sessionStorage - 用于臨時保存同一窗口(或標簽頁)的數據,在關閉窗口或標簽頁之后將會刪除這些數據。
在使用 web 存儲前,應檢查瀏覽器是否支持 localStorage 和sessionStorage:
不管是 localStorage,還是 sessionStorage,可使用的API都相同,常用的有如下幾個(以localStorage為例):
保存數據:localStorage.setItem(key,value);
讀取數據:localStorage.getItem(key);
刪除單個數據:localStorage.removeItem(key);
刪除所有數據:localStorage.clear();
得到某個索引的key:localStorage.key(index);
四、HTML5 應用程序緩存
HTML5 -應用程序緩存=>使用文章鏈接跳轉點這里
五、HTML5 服務器發送事件(Server-Sent Events)
Server-Sent 事件指的是網頁自動獲取來自服務器的更新。
以前也可能做到這一點,前提是網頁不得不詢問是否有可用的更新。通過服務器發送事件,更新能夠自動到達。
例子:Facebook/Twitter 更新、股價更新、新的博文、賽事結果等。
所有主流瀏覽器均支持服務器發送事件,除了 Internet Explorer。
六、HTML5 WebSocket
WebSocket 是 HTML5 開始提供的一種在單個 TCP 連接上進行全雙工通訊的協議。
WebSocket 使得客戶端和服務器之間的數據交換變得更加簡單,允許服務端主動向客戶端推送數據。在 WebSocket API 中,瀏覽器和服務器只需要完成一次握手,兩者之間就直接可以創建持久性的連接,并進行雙向數據傳輸。
在 WebSocket API 中,瀏覽器和服務器只需要做一個握手的動作,然后,瀏覽器和服務器之間就形成了一條快速通道。兩者之間就直接可以數據互相傳送。
現在,很多網站為了實現推送技術,所用的技術都是 Ajax 輪詢。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然后由服務器返回最新的數據給客戶端的瀏覽器。這種傳統的模式帶來很明顯的缺點,即瀏覽器需要不斷的向服務器發出請求,然而HTTP請求可能包含較長的頭部,其中真正有效的數據可能只是很小的一部分,顯然這樣會浪費很多的帶寬等資源。
HTML5 定義的 WebSocket 協議,能更好的節省服務器資源和帶寬,并且能夠更實時地進行通訊。
詳情和代碼示例:
七、HTTP狀態消息
1xx: 信息
2xx: 成功
3xx: 重定向
4xx: 客戶端錯誤
5xx: 服務器錯誤
詳情
八、HTTP 方法:GET 對比 POST
兩種最常用的 HTTP 方法是:GET 和 POST。
什么是 HTTP ?
超文本傳輸協議(HTTP)的設計目的是保證客戶端與服務器之間的通信。
HTTP 的工作方式是客戶端與服務器之間的請求-應答協議。
web 瀏覽器可能是客戶端,而計算機上的網絡應用程序也可能作為服務器端。
舉例:客戶端(瀏覽器)向服務器提交 HTTP 請求;服務器向客戶端返回響應。響應包含關于請求的狀態信息以及可能被請求的內容。
GET - 從指定的資源請求數據。
POST - 向指定的資源提交要被處理的數據。
GET 方法
請注意,查詢字符串(名稱/值對)是在 GET 請求的 URL 中發送的:
有關 GET 請求的其他一些注釋:
GET 請求可被緩存
GET 請求保留在瀏覽器歷史記錄中
GET 請求可被收藏為書簽
GET 請求不應在處理敏感數據時使用
GET 請求有長度限制
GET 請求只應當用于取回數據
POST 方法
請注意,查詢字符串(名稱/值對)是在 POST 請求的 HTTP 消息主體中發送的:
有關 POST 請求的其他一些注釋:
POST 請求不會被緩存
POST 請求不會保留在瀏覽器歷史記錄中
POST 不能被收藏為書簽
POST 請求對數據長度沒有要求
下面的表格列出了其他一些 HTTP 請求方法:
最后送福利了,自己是從事了五年的前端工程師,整理了一份最全面前端學習資料,只要私信:“前端"等3秒后即可獲取地址,
里面概括應用網站開發,css,html,JavaScript,jQuery,Ajax,node,angular等。等多個知識點高級進階干貨的相關視頻資料,等你來拿
3月30日消息,蘋果 iOS 16.4 系統已經向用戶推送,蘋果在這個版本中開放了 Web Push API。這意味著,網站可以通過 Safari 向用戶推送通知。
用 Safari 打開網頁,選擇下方的分享按鈕,再選擇添加到主屏幕,即可將網頁 icon 添加到手機屏幕,當收到通知后, icon 右上角可顯示通知數量。
這僅適用于添加到主屏幕的網頁,網頁使用 HTML5 標準 Web Push API 推送通知。
可以通過 設置>通知 來調整網頁權限,對于不想收到通知的網頁,可以關閉通知權限。
(8148716)
文來自“糊糊糊糊糊了”的分享,原題《實時消息推送整理》,有優化和改動。
對Web端即時通訊技術熟悉的開發者來說,我們回顧網頁端IM的底層通信技術,從短輪詢、長輪詢,到后來的SSE以及WebSocket,使用門檻越來越低(早期的長輪詢Comet這類技術實際屬于hack手段,使用門檻并不低),技術手段越來越先進,網頁端即時通訊技術的體驗也因此越來越好。
但上周在編輯《IM掃碼登錄技術專題》系列文章第3篇的時候忽然想到,之前的這些所謂的網頁端即時通訊“老技術”相對于當紅的WebSocket,并非毫無用武之地。就拿IM里的掃碼登錄功能來說,用短輪詢技術就非常合適,完全沒必要大炮打蚊子上WebSocket。
所以,很多時候沒必要盲目追求新技術,相對應用場景來說適合的才是最好的。對于即時通訊網的im和消息推送這類即時通訊技術開發者來說,掌握WebSocket固然很重要,但了解短輪詢、長輪詢等這些所謂的Web端即時通訊“老技術”仍然大有裨益,這也正是整理分享本文的重要原因。
[1] 新手入門貼:史上最全Web端即時通訊技術原理詳解
[2] 詳解Web端通信方式的演進:從Ajax、JSONP 到 SSE、Websocket
[3] Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE
對于IM/消息推送這類即時通訊系統而言,系統的關鍵就是“實時通信”能力。
從表面意思上來看,“實時通信”指的是:
類比于傳統的C/S請求模型,“實時通信”時客戶端不需要主觀地發送請求去獲取自己關心的內容,而是由服務器端進行“推送”。
注意:上面的“推送”二字打了引號,實際上現有的幾種技術實現方式中,并不是服務器端真正主動地推送,而是通過一定的手段營造了一種“實時通信”的假象。
就目前現有的幾種技術而言,主要有以下幾類:
以下正文將針對這幾種技術方案,為你一一解惑。
為了幫助讀者更好的理解本文內容,筆者專門寫了一個較完整的Demo,Demo會以一個簡易聊天室的例子來分別通過上述的四種技術方式實現(代碼存在些許bug,主要是為了做演示用,別介意)。
完整Demo源碼打包下載:
(請從同步鏈接附件中下載:http://www.52im.net/thread-3555-1-1.html)
Demo的運行效果(動圖):
有興趣可以自行下載研究學習。
短輪詢的實現原理:
邏輯如下圖所示:
使用短輪詢的優點:基礎不需要額外的開發成本,請求數據,解析數據,作出響應,僅此而已,然后不斷重復。
缺點也顯而易見:
短輪詢客戶的代碼實現(片段節選):
var ShortPollingNotification = {
datasInterval: null,
subscribe: function() {
this.datasInterval = setInterval(function() {
Request.getDatas().then(function(res) {
window.ChatroomDOM.renderData(res);
});
}, TIMEOUT);
return this.unsubscribe;
},
unsubscribe: function() {
this.datasInterval && clearInterval(this.datasInterval);
}
}
PS:完整代碼,請見本文“4、本文配套Demo和代碼”一節。
對應本文配套Demo的運行效果如下(動圖):
下面是對應的請求,注意左下角的請求數量一直在變化:
在上圖中,每隔1s就會發送一個請求,看起來效果還不錯,但是如果將timeout的值設置成5s,效果將大打折扣。如下圖所示。
將timeout值設置成5s時的Demo運行效果(動圖):
長輪詢的基本原理:
邏輯如下圖所示:
長輪詢是基于短輪詢上的改進版本:主要是減少了客戶端發起Http連接的開銷,改成了在服務器端主動地去判斷所關心的內容是否變化。
所以其實輪詢的本質并沒有多大變化,變化的點在于:
長輪詢客戶的代碼實現(片段節選):
// 客戶端
var LongPollingNotification = {
// ....
subscribe: function() {
var that = this;
// 設置超時時間
Request.getV2Datas(this.getKey(),{ timeout: 10000 }).then(function(res) {
var data = res.data;
window.ChatroomDOM.renderData(res);
// 成功獲取數據后會再次發送請求
that.subscribe();
}).catch(function(error) {
// timeout 之后也會再次發送請求
that.subscribe();
});
return this.unsubscribe;
}
// ....
}
筆者采用的是express,默認不支持hold住請求,因此用了一個express-longpoll的庫來實現。
下面是一個原生不用庫的實現(這里只是介紹原理),整體的思路是:如果服務器端支持hold住請求的話,那么在一定的時間內會自輪詢,然后期間通過比較key值,判斷是否返回新數據。
以下是具體思路:
代碼如下:
// 服務器端
router.get('/v2/datas', function(req, res) {
const key = _.get(req.query, 'key', '');
let contentKey = chatRoom.getContentKey();
while(key === contentKey) {
sleep.sleep(5);
contentKey = chatRoom.getContentKey();
}
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
res.json({
code: 200,
data: { connectors: connectors, messages: messages, key: contentKey },
});
});
以下是用 express-longpoll的實現片段:
// mini-chatroom/public/javascripts/server/longPolling.js
function pushDataToClient(key, longpoll) {
var contentKey = chatRoom.getContentKey();
if(key !== contentKey) {
var connectors = chatRoom.getConnectors();
var messages = chatRoom.getMessages();
long poll.publish(
'/v2/datas',
{
code: 200,
data: {connectors: connectors, messages: messages, key: contentKey},
}
);
}
}
long poll.create("/v2/datas", function(req, res, next) {
key = _.get(req.query, 'key', '');
pushDataToClient(key, longpoll);
next();
});
intervalId = setInterval(function() {
pushDataToClient(key, longpoll);
}, LONG_POLLING_TIMEOUT);
PS:完整代碼,請見本文“4、本文配套Demo和代碼”一節。
為了方便演示,我將客戶端發起請求的timeout改成了4s,注意觀察下面的截圖:
可以看到,斷開連接的兩種方式,要么是超時,要么是請求有數據返回。
這是長輪詢技術的另一個種實現方案。
該方案的具體的原理為:
因不篇幅原因,在此不作深入介紹,有興趣的同學可以詳讀《新手入門貼:史上最全Web端即時通訊技術原理詳解》一文中的“3.3.2 基于iframe的數據流”一節。
從純技術的角度講:上兩節介紹的短輪詢和長輪詢技術,服務器端是無法主動給客戶端推送消息的,都是客戶端主動去請求服務器端獲取最新的數據。
本節要介紹的SSE是一種可以主動從服務端推送消息的技術。
SSE的本質其實就是一個HTTP的長連接,只不過它給客戶端發送的不是一次性的數據包,而是一個stream流,格式為text/event-stream。所以客戶端不會關閉連接,會一直等著服務器發過來的新的數據流,視頻播放就是這樣的例子。
簡單來說,SSE就是:
SSE的技術原理如下圖所示:
SSE基本的使用方法,可以參看 SSE 的API文檔,地址是:https://developer.mozilla.org/en ... _server-sent_events。
目前除了IE以及低版本的瀏覽器不支持,絕大多數的現代瀏覽器都支持SSE:
(上圖來自:https://caniuse.com/?search=Server-Sent-Events)
// 客戶端
var SSENotification = {
source: null,
subscribe: function() {
if('EventSource'inwindow) {
this.source = newEventSource('/sse');
this.source.addEventListener('message', function(res) {
const d = res.data;
window.ChatroomDOM.renderData(JSON.parse(d));
});
}
return this.unsubscribe;
},
unsubscribe: function() {
this.source && this.source.close();
}
}
// 服務器端
router.get('/sse', function(req, res) {
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
const response = { code: 200, data: { connectors: connectors, messages: messages } };
res.writeHead(200, {
"Content-Type":"text/event-stream",
"Cache-Control":"no-cache",
"Connection":"keep-alive",
"Access-Control-Allow-Origin": '*',
});
res.write("retry: 10000\n");
res.write("data: "+ JSON.stringify(response) + "\n\n");
var unsubscribe = Event.subscribe(function() {
const connectors = chatRoom.getConnectors();
const messages = chatRoom.getMessages();
const response = { code: 200, data: { connectors: connectors, messages: messages } };
res.write("data: "+ JSON.stringify(response) + "\n\n");
});
req.connection.addListener("close", function() {
unsubscribe();
}, false);
});
下面是控制臺的情況,注意觀察響應類型:
詳情中注意查看請求類型,以及EventStream消息類型:
PS:有關SSE更詳盡的資料就不在這里展開了,有興趣的同學可以詳讀《SSE技術詳解:一種全新的HTML5服務器推送事件技術》、《使用WebSocket和SSE技術實現Web端消息推送》。
PS:本小節內容引用自《Web端即時通訊實踐干貨:如何讓WebSocket斷網重連更快速?》一文的“3、快速了解WebSocket”。
WebSocket誕生于2008年,在2011年成為國際標準,現在所有的瀏覽器都已支持(詳見《新手快速入門:WebSocket簡明教程》)。它是一種全新的應用層協議,是專門為web客戶端和服務端設計的真正的全雙工通信協議,可以類比HTTP協議來了解websocket協議。
(圖片引用自《WebSocket詳解(四):刨根問底HTTP與WebSocket的關系(上篇)》)
它們的不同點:
它們的相同點:
兩者和TCP的關系圖:
(圖片引用自《新手快速入門:WebSocket簡明教程》)
有關Http和WebSocket的關系,可以詳讀:
《WebSocket詳解(四):刨根問底HTTP與WebSocket的關系(上篇)》
《WebSocket詳解(五):刨根問底HTTP與WebSocket的關系(下篇)》
有關WebSocket和Socket的關系,可以詳讀:《WebSocket詳解(六):刨根問底WebSocket與Socket的關系》.
WebSocket技術特征總結下就是:
WebSocket的技術原理如下圖所示:
關于WebSocket API方面的知識,這里不再作講解,可以自己查閱:https://developer.mozilla.org/en-US/docs/Web/API/WebSocket
WebSocket兼容性良好,基本支持所有現代瀏覽器。
(上圖來自:https://caniuse.com/mdn-api_websocket)
筆者這里采用的是socket.io,是基于WebSocket的封裝,提供了客戶端以及服務器端的支持。
// 客戶端
var WebsocketNotification = {
// ...
subscribe: function(args) {
var connector = args[1];
this.socket = io();
this.socket.emit('register', connector);
this.socket.on('register done', function() {
window.ChatroomDOM.renderAfterRegister();
});
this.socket.on('data', function(res) {
window.ChatroomDOM.renderData(res);
});
this.socket.on('disconnect', function() {
window.ChatroomDOM.renderAfterLogout();
});
}
// ...
}
// 服務器端
var io = socketIo(httpServer);
io.on('connection', (socket) => {
socket.on('register', function(connector) {
chatRoom.onConnect(connector);
io.emit('register done');
var data = chatRoom.getDatas();
io.emit('data', { data });
});
socket.on('chat', function(message) {
chatRoom.receive(message);
var data = chatRoom.getDatas();
io.emit('data', { data });
});
});
PS:完整代碼,請見本文“4、本文配套Demo和代碼”一節。
響應格式如下:
隨著HTML5的普及率越來越高,WebSocket的應用也越來越普及,關于WebSocket的學習資料網上很容易找到,限于篇幅本文就不深入展開這個話題。
如果想進一步深入學習WebSocket的方方面面,以下文章值得一讀:
《新手快速入門:WebSocket簡明教程》
《WebSocket詳解(一):初步認識WebSocket技術》
《WebSocket詳解(二):技術原理、代碼演示和應用案例》
《WebSocket詳解(三):深入WebSocket通信協議細節》
《WebSocket詳解(四):刨根問底HTTP與WebSocket的關系(上篇)》
《WebSocket詳解(五):刨根問底HTTP與WebSocket的關系(下篇)》
《WebSocket詳解(六):刨根問底WebSocket與Socket的關系》
《理論聯系實際:從零理解WebSocket的通信原理、協議格式、安全性》
《微信小程序中如何使用WebSocket實現長連接(含完整源碼)》
《八問WebSocket協議:為你快速解答WebSocket熱門疑問》
《Web端即時通訊實踐干貨:如何讓你的WebSocket斷網重連更快速?》
《WebSocket從入門到精通,半小時就夠!》
《WebSocket硬核入門:200行代碼,教你徒手擼一個WebSocket服務器》
《長連接網關技術專題(四):愛奇藝WebSocket實時推送網關技術實踐》
短輪詢、長輪詢實現成本相對比較簡單,適用于一些實時性要求不高的消息推送,在實時性要求高的場景下,會存在延遲以及會給服務器帶來更大的壓力。
SSE只能是服務器端推送消息,因此對于不需要雙向通信的項目比較適用。
WebSocket目前而言實現成本相對較低,適合于雙工通信,對于多人在線,要求實時性較高的項目比較實用。
學習交流:
- 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK
本文已同步發布于“即時通訊技術圈”公眾號。
同步發布鏈接是:http://www.52im.net/thread-3555-1-1.html
*請認真填寫需求信息,我們會在24小時內與您取得聯系。