WebSocket簡述-通過node.js的基本實現(xiàn)
基本概念
WebSocket是自Html5開始在單個TCP連接上進行全雙工通信1的協(xié)議,它使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)。在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進行雙向數(shù)據(jù)傳輸。
為什么要使用WebSocket
HTTP 并不是為了保持打開連接以便服務(wù)器頻繁地將數(shù)據(jù)推送到 Web 瀏覽器。以前,在系統(tǒng)開發(fā)的過程中大多數(shù) Web 應用程序?qū)⑼ㄟ^頻繁的異步 JavaScript 和 XML (AJAX)實現(xiàn)長輪詢;
與之相比服務(wù)器推送比長輪詢更高效和可擴展,因為 Web 瀏覽器不必通過 AJAX 請求流不斷地請求更新,有更強的及時性且能節(jié)約資源。同時WebSockets 是全雙工連接,因此客戶端也可以將數(shù)據(jù)推送到服務(wù)器
node.js 針對 WebSocket的簡易實現(xiàn)
這里采用node.js對功能進行展示, node.js的使用在這里不作額外介紹
服務(wù)端 server.js
// 引入express框架
var app = require('express')();
var server = require('http').Server(app);
// 引入ws框架支持webSocket實現(xiàn)
var WebSocket = require('ws');
// 針對8080接口進行監(jiān)聽
var wss = new WebSocket.Server({ port: 8080 });
// 當建立連接后,打印日志
wss.on('connection', function connection(ws) {
console.log('server: receive connection.');
// 同時返回服務(wù)端收到的信息
ws.on('message', function incoming(message) {
console.log('server: received: %s', message);
});
// 返回信息
ws.send('receive');
});
// 綁定訪問地址
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
app.listen(3000);
客戶端index.html
<script>
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
console.log('ws onopen');
ws.send('from client: hello');
};
ws.onmessage = function (e) {
console.log('ws onmessage');
console.log('from server: ' + e.data);
};
</script>
訪問localhost:3000 會打開客戶端頁面,并對應向服務(wù)端發(fā)起請求,可以查看到應有的日志
WebSocket連接是如何建立的
打開控制臺可以跟蹤發(fā)現(xiàn),首先是客戶端通過標準的http請求 get方法發(fā)起升級協(xié)議請求
GET / HTTP/1.1
Host: localhost:8080
Origin: http://127.0.0.1:3000
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: JYB++OaZz3cuJvOOhZ2xHGghN80=
服務(wù)端對應響應升級完成鏈接建立
WebSocket通訊方式
WebSocket客戶端、服務(wù)端通信的最小單位是幀(frame),由1個或多個幀組成一條完整的消息(message)。
發(fā)送端:將消息切割成多個幀,并發(fā)送給服務(wù)端;
接收端:接收消息幀,并將關(guān)聯(lián)的幀重新組裝成完整的消息;
WebSocket的每條消息可能被切分成多個數(shù)據(jù)幀。當WebSocket的接收方收到一個數(shù)據(jù)幀時,會根據(jù)FIN的值來判斷,是否已經(jīng)收到消息的最后一個數(shù)據(jù)幀。
FIN=1表示當前數(shù)據(jù)幀為消息的最后一個數(shù)據(jù)幀,此時接收方已經(jīng)收到完整的消息,可以對消息進行處理。FIN=0,則接收方還需要繼續(xù)監(jiān)聽接收其余的數(shù)據(jù)幀。
此外,opcode在數(shù)據(jù)交換的場景下,表示的是數(shù)據(jù)的類型。0x01表示文本,0x02表示二進制。而0x00比較特殊,表示延續(xù)幀(continuation frame),顧名思義,就是完整消息對應的數(shù)據(jù)幀還沒接收完。
WebSocket的連接保持
WebSocket為了保持客戶端、服務(wù)端的實時雙向通信,需要確??蛻舳恕⒎?wù)端之間的TCP通道保持連接沒有斷開。然而,對于長時間沒有數(shù)據(jù)往來的連接,如果依舊長時間保持著,可能會浪費包括的連接資源。
但不排除有些場景,客戶端、服務(wù)端雖然長時間沒有數(shù)據(jù)往來,但仍需要保持連接。這個時候,可以采用心跳來實現(xiàn)。
發(fā)送方->接收方:ping
接收方->發(fā)送方:pong
對應實現(xiàn)代碼
ws.ping('', false, true);
node.js WebSocket api示例
通過一個代碼完整展示文章來源:http://www.zghlxwxcb.cn/news/detail-486099.html
<h2>Websocket Echo Client</h2>
<div id="output"></div>
// 初始化連接和事件
function setup() {
output = document.getElementById("output");
ws = new WebSocket("ws://echo.websocket.org/echo");
// 監(jiān)聽open
ws.onopen = function (e) {
log("Connected");
sendMessage("Hello WebSocket!");
}
// 監(jiān)聽close
ws.onclose = function (e) {
log("Disconnected: " + e.reason);
}
//監(jiān)聽errors
ws.onerror = function (e) {
log("Error ");
}
// 監(jiān)聽 messages
ws.onmessage = function (e) {
log("Message received: " + e.data);
//收到消息后關(guān)閉
ws.close();
}
}
// 發(fā)送消息
function sendMessage(msg) {
ws.send(msg);
log("Message sent");
}
// logging
function log(s) {
var p = document.createElement("p");
p.style.wordWrap = "break-word";
p.textContent = s;
output.appendChild(p);
// Also log information on the javascript console
console.log(s);
}
// Start
setup();
-
全雙工通信又稱為雙向同時通信,即通信的雙方可以同時發(fā)送和接收信息的信息交互方式。與之不同的是半雙工通信,雖然他也允許數(shù)據(jù)在兩個方向上傳輸,但是同一時間數(shù)據(jù)只能在一個方向上傳輸 ??文章來源地址http://www.zghlxwxcb.cn/news/detail-486099.html
到了這里,關(guān)于WebSocket簡述及通過node.js的基本實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!