基於 WebSocket 實現 WebGL 3D 拓撲圖實時數據通訊同步(一)


今天沒有延續上一篇講的內容,穿插一段小插曲,WebSocket 實時數據通訊同步的問題,今天我們並不是很純粹地講 WebSocket 相關知識,我們通過 WebGL 3D 拓撲圖來呈現一個有趣的 Demo。接下來我們就看看這個實時數據通訊是一個什么樣的套路。

我們先來聊聊這次 Demo 的思路吧,首先我要有一個 3D 的拓撲圖組件,在上面創建幾個節點,然后通過拉力布局(ForceLayout)將這些節點自動布局,但是有一定,需要在不同的網頁窗口下,對應節點的位置是一樣的,簡單地說就是不同網頁窗口所呈現的節點布局是一樣,而且拖動不同網頁窗口中的任意的節點,都將更新所有頁面窗口,讓所有窗口的呈現都是一樣的。

根據上面的思路,我們該如何去規划呢?既然需要實時數據通訊,那么就需要使用 WebSocket,WebSocket 又是什么呢?WebSocket 是 HTML5 一種新的協議,它沒有標准的 API,各個實現都有自己的一套 API,在這里我們就不去詳細研究 WebSocket 的具體實現,我也講不了,至少現在講不了。

在這里我們用比較易上手的 Node.js 的 Socket.IO 做通訊框架,Socket.IO 讓長連接通訊變得無比簡單,服務器再也不用等待客戶端的請求就可以直接給客戶端發送消息,根據這樣的特性就可以實現數據通訊同步的問題。

我們來寫一個最簡單的例子,將任何一個客戶端發送到服務器的消息,原封不動的轉發到所有連接到服務器的客戶端,我們來看看要實現這樣的一個功能,服務端要怎么設計。

首先我們得搭建一個簡易的 web 服務器。

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.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/chat/ 這上面比我講得清楚,大家可以到上面詳細閱讀,會理解得更全面一點。

由於篇幅的問題,我今天就介紹到這了,下一篇,我們將重點介紹前面說到的結合 HT for Web 的 3D 拓撲圖組件來展現實時數據通訊的效果,讓每個客戶端都同步操作,效果圖如上。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM