今天沒有延續上一篇講的內容,穿插一段小插曲,WebSocket 實時數據通信同步的問題,今天咱們並非很純粹地講 WebSocket 相關知識,咱們經過 WebGL 3D 拓撲圖來呈現一個有趣的 Demo。接下來咱們就看看這個實時數據通信是一個什麼樣的套路。html
咱們先來聊聊此次 Demo 的思路吧,首先我要有一個 3D 的拓撲圖組件,在上面建立幾個節點,而後經過拉力佈局(ForceLayout)將這些節點自動佈局,可是有必定,須要在不一樣的網頁窗口下,對應節點的位置是同樣的,簡單地說就是不一樣網頁窗口所呈現的節點佈局是同樣,並且拖動不一樣網頁窗口中的任意的節點,都將更新全部頁面窗口,讓全部窗口的呈現都是同樣的。node
根據上面的思路,咱們該如何去規劃呢?既然須要實時數據通信,那麼就須要使用 WebSocket,WebSocket 又是什麼呢?WebSocket 是 HTML5 一種新的協議,它沒有標準的 API,各個實現都有本身的一套 API,在這裏咱們就不去詳細研究 WebSocket 的具體實現,我也講不了,至少如今講不了。web
在這裏咱們用比較易上手的 Node.js 的 Socket.IO 作通信框架,Socket.IO 讓長鏈接通信變得無比簡單,服務器不再用等待客戶端的請求就能夠直接給客戶端發送消息,根據這樣的特性就能夠實現數據通信同步的問題。express
咱們來寫一個最簡單的例子,將任何一個客戶端發送到服務器的消息,原封不動的轉發到全部鏈接到服務器的客戶端,咱們來看看要實現這樣的一個功能,服務端要怎麼設計。npm
首先咱們得搭建一個簡易的 web 服務器。json
var app = require('express')(); var http = require('http').Server(app); app.get('/', function(req, res) { res.end('<h1>Hello Message!</h1>'); }); http.listen(4000, function() { console.log('listening on *:4000'); });
以上的代碼的 Node.js 的代碼,將這串代碼貼到一個 js 文件中,好比命名爲 server.js 而後在 Terminal 中 cd 到 server.js 對應的文件夾下,若是 node server.js 後回車,若是發現報了 Cannot find module ‘xxx’ 的字樣,那麼說明你在當前目錄下沒有安裝程序用到的相關包。那麼咱們在當前目錄下建立一個叫 package.json 的文件,而後把下面的程序拷貝到該文件中,而後在 Terminal 中輸入 npm install,等安裝完後,就能夠正常啓動服務器了。瀏覽器
{ "name": "socket-example", "version": "0.0.1", "description": "my first socket.io app", "dependencies": { "express": "^4.10.2", "socket.io": "^1.4.8" } }
啓動後,你在瀏覽器上輸入 localhost:4000 就能夠看到 Hello Message! 的字樣。這是最簡單的 HTTP 服務器,那麼咱們如何在上面加上 WebSocket 的功能呢呢?眼尖的同窗可能已經發現上面的 package.json 的內容已經包含了 Socket.IO,那麼 Socket.IO 要怎麼用呢,怎麼樣才能達到實時數據通信的效果呢?服務器
var io = require('socket.io')(http); io.on('connection', function(socket) { console.log('a user connected'); socket.on('disconnect', function() { console.log('user disconnected'); }); socket.on('message', function(msg) { io.emit('message', msg); }); });
在 server.js 中加入上面那串代碼,就能夠實現客戶端之間的實時數據通信問題。可是在瀏覽器輸入 localhost:4000 你看到的是 Hello Message! 的字樣,要怎樣才能訪問到具體的 html 網頁內容呢?這個時候就須要稍微修改下咱們的服務器了。app
app.get('/', function(req, res) { res.sendFile(__dirname + '/index.html'); });
也就是將前面提到的 res.end('<h1>Hello Message!</h1>’); 代碼換成 res.sendFile(__dirname + ‘/index.html'); 作個頁面跳轉,從而達到訪問具體 html 網頁的目的,在這邊是是爲了知足 Demo 而作的方案,要搭建一個真正的 http 靜態服務器確定不是這樣子的,搭建 http 靜態服務器我在這邊就不介入研究了,你們剛興趣的話,能夠本身到網上搜索學習。框架
那麼客戶端該如何實現來展示服務端的實時通信呢?
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Socket.IO Message</title> <style media="screen"> #send { font-size: 14px; } #msgList { list-style-type: none; margin: 10px 0px; padding: 0; } #msgList li { padding: 5px 10px; } #msgList li:nth-child(odd) { background: #eee; } </style> <script src="/socket.io/socket.io.js"></script> <script> var socket = io(); var init = function() { var input = document.getElementById('message'), sendFunc = function() { var msg = input.value; if (!msg) return; socket.emit('message', input.value); input.value = ''; }; input.addEventListener('keyup', function(e) { if (e.keyCode === 13) { sendFunc(); } }); var list = document.getElementById('msgList'); socket.on('message', function(msg) { var li = document.createElement('li'); li.innerHTML = msg; list.insertBefore(li, list.childNodes[0]); }); var btn = document.getElementById('send'); btn.addEventListener('click', sendFunc); }; </script> </head> <body onload="init();"> Message: <input id="message" /> <button type="button" id="send">Send</button><br/> <ul id="msgList"></ul> </body> </html>
以上代碼就能夠作到數據同步了,具體我來解釋下。
頁面很簡單,有一個 input 文本框,和一個 Send 按鈕,還有一個 ul 無序列表用來顯示用戶發送的內容,當用戶在 input 文本框中輸入內容後,按下 enter 鍵或者點擊 Send 按鈕都會想服務器發送文本框中填入的內容,而且服務器會將這條消息原封不動地推送到全部的客戶端中,在客戶端接收到消息後,就會想 ul 無序列表中填入消息。
這個 Demo 在 http://socket.io/get-started/... 這上面比我講得清楚,你們能夠到上面詳細閱讀,會理解得更全面一點。
因爲篇幅的問題,我今天就介紹到這了,下一篇,咱們將重點介紹前面說到的結合 HT for Web 的 3D 拓撲圖組件來展示實時數據通信的效果,讓每一個客戶端都同步操做,效果圖如上。