如何在snap中利用socket.io及websocket来进行实时数据更新

来源:互联网 发布:知乎 恩牛网络 编辑:程序博客网 时间:2024/04/29 19:07

Socket.io可以使得我们的服务器和客户端进行双向的实时的数据交流。它比HTTP来说更具有传输数据量少的优点。同样地,websocket也具有同样的优点。你可以轻松地把你的数据发送到服务器,并收到以事件为驱动的响应,而不用去查询。在今天的教程中,我们来讲一下如何利用socket.io和websocket来做一个双向的通讯。


1)创建一个socket.io的服务器


首先我们先看一下我完成的一个项目:

https://github.com/liu-xiao-guo/socketio

我们首先看一下我们的snapcraft.yaml文件:

snapcraft.yaml

name: socketioversion: "0.1"summary: A simple shows how to make use of socket iodescription: socket.io snap examplegrade: stableconfinement: strictapps:  socket:    command: bin/socketio    daemon: simple    plugs: [network-bind]parts:  nod:    plugin: nodejs    source: .   

这是一个nodejs的项目。我们使用了nodejs的plugin。我们的package.json文件如下:

package.json

{  "name": "socketio",  "version": "0.0.1",  "description": "Intended as a nodejs app in a snap",  "license": "GPL-3.0",  "author": "xiaoguo, liu",  "private": true,  "bin": "./app.js",  "dependencies": {    "express": "^4.10.2",    "nodejs-websocket": "^1.7.1",    "socket.io": "^1.3.7"  }}

由于我们需要使用到webserver,所有我们安装了express架构包。另外,我们使用到socket.io及websocket,所有,我们把这些包都打入到我们的snap包中。

再来看看我们的应用app.js的设计:

app.js

#!/usr/bin/env nodevar express = require('express');var app = require('express')();var http = require('http').Server(app);var io = require('socket.io')(http);app.get('/', function(req, res){   res.sendFile(__dirname + '/www/index.html');});app.use(express.static(__dirname + '/www'));//Whenever someone connects this gets executedio.on('connection', function(socket){  console.log('A user connected');    setInterval(function(){  var value = Math.floor((Math.random() * 1000) + 1);  io.emit('light-sensor-value', '' + value);  // console.log("value: " + value)    // This is another way to send data  socket.send(value);  }, 2000);   //Whenever someone disconnects this piece of code executed  socket.on('disconnect', function () {    console.log('A user disconnected');  });});http.listen(4000, function(){  console.log('listening on *:4000');});var ws = require("nodejs-websocket")console.log("Going to create the server")String.prototype.format = function() {    var formatted = this;    for (var i = 0; i < arguments.length; i++) {        var regexp = new RegExp('\\{'+i+'\\}', 'gi');        formatted = formatted.replace(regexp, arguments[i]);    }    return formatted;}; // Scream server example: "hi" -> "HI!!!" var server = ws.createServer(function (conn) {    console.log("New connection")var connected = true;        conn.on("text", function (str) {        console.log("Received "+str)        conn.sendText(str.toUpperCase()+"!!!")    })        conn.on("close", function (code, reason) {        console.log("Connection closed")        connected = false    })          setInterval(function(){  var value = Math.floor((Math.random() * 1000) + 1);  var data = '{"data":"{0}"}'.format(value)  if (connected){conn.send(data);  }  }, 2000); }).listen(4001)

在代码的第一部分,我们创建了一个webserver,它使用的端口地址是4000。我们也同时启动了socket.io服务器,等待客户端的连接。一旦有一个连接的话,我们使用如下的代码每过一段时间来发送一些数据:

//Whenever someone connects this gets executedio.on('connection', function(socket){  console.log('A user connected');    setInterval(function(){  var value = Math.floor((Math.random() * 1000) + 1);  io.emit('light-sensor-value', '' + value);  // console.log("value: " + value)    // This is another way to send data  socket.send(value);  }, 2000);   //Whenever someone disconnects this piece of code executed  socket.on('disconnect', function () {    console.log('A user disconnected');  });});

虽然这些数据是一些随机的,但是我们主要用来展示它是如何工作的。在实际的应用中,这些数据可以是从一些传感器中得到的。在我们的客户端中,我们可以打开webserver运行的地址:


我们可以看到数据不断地进来,并在我们的客户端中显示出来。具体的设计请参考在www目录中的index.html文件。


2)创建一个websocket的服务器


在我们的app.js中,我们利用如下的代码来实现一个websocket的服务器。端口地址为4001。

app.js


var ws = require("nodejs-websocket")console.log("Going to create the server")String.prototype.format = function() {    var formatted = this;    for (var i = 0; i < arguments.length; i++) {        var regexp = new RegExp('\\{'+i+'\\}', 'gi');        formatted = formatted.replace(regexp, arguments[i]);    }    return formatted;}; // Scream server example: "hi" -> "HI!!!" var server = ws.createServer(function (conn) {    console.log("New connection")var connected = true;        conn.on("text", function (str) {        console.log("Received "+str)        conn.sendText(str.toUpperCase()+"!!!")    })        conn.on("close", function (code, reason) {        console.log("Connection closed")        connected = false    })          setInterval(function(){  var value = Math.floor((Math.random() * 1000) + 1);  var data = '{"data":"{0}"}'.format(value)  if (connected){conn.send(data);  }  }, 2000); }).listen(4001)

同样地,一旦有个连接,我们每隔两秒钟发送一个数据到我们的客户端。为了说明问题方便,我们设计了一个QML的客户端。

Main.qml


import QtQuick 2.4import Ubuntu.Components 1.3import Ubuntu.Components.Pickers 1.3import Qt.WebSockets 1.0import QtQuick.Layouts 1.1MainView {    // objectName for functional testing purposes (autopilot-qt5)    objectName: "mainView"    // Note! applicationName needs to match the "name" field of the click manifest    applicationName: "dialer.liu-xiao-guo"    width: units.gu(60)    height: units.gu(85)    function interpreteData(data) {        var json = JSON.parse(data)        console.log("Websocket data: " + data)        console.log("value: " + json.data)        mainHand.value = json.data    }    WebSocket {        id: socket        url: input.text        onTextMessageReceived: {            console.log("something is received!: " + message);            interpreteData(message)        }        onStatusChanged: {            if (socket.status == WebSocket.Error) {                console.log("Error: " + socket.errorString)            } else if (socket.status == WebSocket.Open) {                // socket.sendTextMessage("Hello World....")            } else if (socket.status == WebSocket.Closed) {            }        }        active: true    }    Page {        header: PageHeader {            id: pageHeader            title: i18n.tr("dialer")        }        Item {            anchors {                top: pageHeader.bottom                left: parent.left                right: parent.right                bottom: parent.bottom            }            Column {                anchors.fill: parent                spacing: units.gu(1)                anchors.topMargin: units.gu(2)                Dialer {                    id: dialer                    size: units.gu(30)                    minimumValue: 0                    maximumValue: 1000                    anchors.horizontalCenter: parent.horizontalCenter                    DialerHand {                        id: mainHand                        onValueChanged: console.log(value)                    }                }                TextField {                    id: input                    width: parent.width                    text: "ws://192.168.1.106:4001"                }                Label {                    id: value                    text: mainHand.value                }            }        }    }}

运行我们的服务器及客户端:



我们可以看到我们数值在不断地变化。这个客户端的代码在:https://github.com/liu-xiao-guo/dialer

在这篇文章中,我们展示了如何利用socket.io及websocket来进行双向的实时的通讯。在很多的物联网的应用中,我们可以充分利用这些通讯协议来更好地设计我们的应用。

更多阅读:https://github.com/snapcore/snapcraft/tree/master/demos/webchat
1 0