websocketd 是WebSocket守护进程,它负责处理WebSocket连接,启动您的程序来处理WebSockets,并在程序和Web浏览器之间传递消息。

 安装:websocketd 

wget https:///joewalnes/websocketd/releases/download/v0.2.12/websocketd-0.2.12-linux_amd64.zipunzip  websocketd-0.2.12-linux_amd64.zip

解压后生成这个文件:websocketd

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd

复制该文件到 /usr/bin目录下,修改环境变量

sudo cp websocketd /usr/bin/websocketdsudo vim /etc/profile

export  PATH=$PATH:/usr/bin/websocketd

可能出现的错误:如果修改了/etc/profile,那么编辑结束后执行source profile 或 执行点命令 ./profile,PATH的值就会立即生效了,但是会提示以下错误:

#source /etc/profile   之后为什么会出现
command not found

解决办法,直接切换到root 用户模式既可,再次执行source profile 就可以了,输入help 看是否配置合适,如下所示:

tinywan@tinywan:~/shell$ websocketd --help
websocketd (0.2.12 (go1.6 linux-amd64) --)

websocketd is a command line tool that will allow any executable program
that accepts input on stdin and produces output on stdout to be turned into
a WebSocket server.

Usage:

  Export a single executable program a WebSocket server:
    websocketd [options] COMMAND [command args]

  Or, export an entire directory of executables as WebSocket endpoints:
    websocketd [options] --dir=SOMEDIR

Options:  --port=PORT                    HTTP port to listen on.  --address=ADDRESS              Address to bind to (multiple options allowed)
                                 Use square brackets to specify IPv6 address. 
                                 Default: "" (all)
开启WebSocketd 服务Tinywan
tinywan@tinywan:~/shell$ websocketd --port=63800 ./count.sh Mon, 08 May 2017 17:26:50 +0800 | INFO   | server     |  | Serving using application   : ./count.sh Mon, 08 May 2017 17:26:50 +0800 | INFO   | server     |  | Starting WebSocket server   : ws://tinywan:8080/

测试代码:count.sh

#!/bin/bashfor ((COUNT = 1; COUNT <= 10; COUNT++)); do
  echo $COUNT  sleep 1done

运行脚本时你可能会遇到以下错误:

root@TinywanAliYun:/home/www/bin# websocketd --port=63800 ./count.sh 
Unable to locate specified COMMAND './count.sh' in OS path.

Usage:

  Export a single executable program a WebSocket server:
    websocketd [options] COMMAND [command args]

  Or, export an entire directory of executables as WebSocket endpoints:
    websocketd [options] --dir=SOMEDIR

  Or, show extended help message using:
    websocketd --help

请赋予权限,使其可执行:

$ chmod +x ./count.sh

随便打开一个浏览器,在console中输入一下代码测试:

var ws = new WebSocket('ws://192.168.18.12:63800/');
ws.onopen = function() {
    console.log('CONNECT');
};
ws.onclose = function() {
    console.log('DISCONNECT');
};
ws.onmessage = function(event) {
    console.log('MESSAGE: ' + event.data);
};

(1)测试结果如下所示:

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd技巧_02

(2)新建立一个客户端测试client.html

<!doctype html><html lang=""><head>
    <meta charset="utf-8">
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>websocketdtitle>head><body><h2>websocketd 客户端的简单测试h2><pre id="log">pre><script>
    // helper function: log message to screen
    function log(msg) {
        document.getElementById('log').textContent += msg + '\n';
    }    // setup websocket with callbacks
    var ws = new WebSocket('ws://192.168.18.12:8080/');
    ws.onopen = function() {
        console.log('CONNECT');
    };
    ws.onclose = function() {
        console.log('DISCONNECT');
    };
    ws.onmessage = function(event) {
        console.log('MESSAGE: ' + event.data);
    };script>body>html>

在查看结果信息,查看结果已经ok

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd实战_03

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd实战_04

 查看服务端信息

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd技巧_05

我本机IP地址为,也就是client.html客户端

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd实战_06

 websocketd --port=9501 --devconsole luajit ./json_ws.lua

》》》实际案例,使用WebSocketd 实时监控内存信息

1、编写脚本,system_info_send_websocketd.sh

#!/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin

SHELL_DIR="/home/www/bin"SHELL_NAME="system_info_websocketd"SHELL_TIME=$(date '+%Y-%m-%d')
SHELL_LOG="${SHELL_DIR}/${SHELL_NAME}-${SHELL_TIME}.log"REDIS_MEMORY_KEYS_NAME="REDIS_MEMORY_INFO:001"REDIS_DISH_KEYS_NAME="REDIS_DISH_INFO:001"while(true)    do
        FIND_DATA=$(cat /proc/meminfo | grep "MemFree:" | awk '{print $2}')        echo  "[$SHELL_TIME]: FIND_DATA = $FIND_DATA INSERT_RES = ${INSERT_RES} CUT_LIST_LEN = ${CUT_LIST_LEN}" >> $SHELL_LOG        echo   '{"data":'"${FIND_DATA}"',"errcode":0,"errmsg":0}'
        sleep 2done

2、客户端实时监控代码:

<div class="panel-footer" id="container" style="width: 100%; height: 400px; margin: 0 auto">div><script language="JavaScript">
    //数据获取
    var moniServerIp = "{{moniServerIp}}";    var moniServerSshUsername = "{$moniServerSshUsername}";    var moniServerSshPassword = "{$moniServerSshPassword}";    var wsServerIP = "127.0.0.1";    var wsServerPort = "12380";    var moniMehtod = "server02";    var moniInterval = 1;    var moniDataUnit = 'MB';    var wsData = 0.0;
    wsSend = {        "action": moniMehtod,        "name": "tinywan",
    };
    $(document).ready(function () {        //----------WebSocket部分--------------
        var ws = new WebSocket("ws://" + wsServerIP + ":" + wsServerPort);
        ws.onopen = function () {
            ws.send(JSON.stringify(wsSend));
        };
        ws.onclose = function () {
            console.log('链接已断开');
            ws.close();
        };
        ws.onmessage = function (e) {            var response = JSON.parse(e.data);            if (Number(response.errcode) !== 0) {
                console.log(String(response.errmsg));
                ws.close();
                alert('出错啦!' + String(response.errmsg));                return;
            }            var divisor = 1;            switch (moniDataUnit.toLocaleLowerCase()) {                case 'mb':
                    divisor = 1024;                    break;
            }
            wsData = response.data / divisor;
            console.log("收到服务端的消息:" + wsData);
        };        //----------highcharts的图标插件部分--------------        Highcharts.setOptions({
            global: {
                useUTC: false
            }
        });

        $('#container').highcharts({
            chart: {
                type: 'spline',
                animation: Highcharts.svg, // don't animate in old IE                marginRight: 10,
                events: {
                    load: function () {                        // set up the updating of the chart each second
                        var series = this.series[0];
                        setInterval(function () {                            // current time
                            var x = (new Date()).getTime(),
                                y = wsData * 1.00;
                            series.addPoint([x, y], true, true);
                        }, 2000);
                    }
                }
            },
            title: {
                text: '服务器【' + moniServerIp + '】内存指标(单位:' + moniDataUnit + ')'
            },
            xAxis: {
                type: 'datetime',
                tickPixelInterval: 150
            },
            yAxis: {
                title: {
                    text: 'MemFree'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function () {                    return '' + this. + '
' +                        Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '
' +                        Highcharts.numberFormat(this.y, 2);                }            },            legend: {                enabled: false            },            exporting: {                enabled: false            },            series: [{                name: 'MemFree指标',                data: (function () {                    // generate an array                    var data = [],                        time = (new Date()).getTime(),                        i;                    for (i = -19; i <= 0; i += 1) {                        data.push({                            x: time + i * 1000,                            y: wsData                        });                    }                    return data;                }())            }]        });    });script><script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">script><script src="http://code.highcharts.com/highcharts.js">script>

3、测试结果:

 Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd实战_07

4、客户端可能会出现超时链接的,可以使用 ReconnectingWebSocket

 var ws = new ReconnectingWebSocket("ws://" + wsServerIP + ":" + wsServerPort);
 》》》》》》》》》》》》 参数详解                   

(1)参数一:--staticdir=.

--staticdir=.  Allow websocketd to serve count.html as a static file
//允许websocketd作为静态文件提供count.html

这个参数是什么意思来,就是在当前项目指定通知执行的语言脚本文件(count.sh)同名的count.html作为静态文件,直接使用http访问

当前目录

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd实战_08

count.sh 文件 (tinywan@tinywan:~/Go/websocket$ cat count.sh)

#!/bin/bash
# Count from 1 to 10, pausing for a second between each iteration.for COUNT in $(seq 1 10); do
  echo $COUNT  sleep 1done

count.html 文件

<!DOCTYPE html><html>
  <head>
    <title>websocketd count exampletitle>
    <style>
      #count {
        font: bold 150px arial;
        margin: auto;
        padding: 10px;
        text-align: center;
      }
    style>
  head>
  <body>

    <div id="count">div>

    <script>
      var ws = new WebSocket('ws://192.168.18.180:8080/');
      ws.onopen = function() {
        document.body.style.backgroundColor = '#cfc';
      };
      ws.onclose = function() {
        document.body.style.backgroundColor = null;
      };
      ws.onmessage = function(event) {
        document.getElementById('count').textContent = event.data;
      };    script>

  body>html>

 打开谷歌浏览器,在地址栏输入:http://192.168.18.180:8080/

  Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd技巧_09

点击count.html后的效果图

   Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd_10

 (2)参数二: --devconsole

  该--devconsole标志使内置的控制台websocketd与WebSocket端点手动交互。

  指向浏览器http://localhost:8080/,您将看到控制台。按复选框连接。

      请注意,您不能同时使用--devconsole和--staticdir。开发控制台旨在提供临时用户界面,直到您构建了真实的用户界面。

开始测试:

  Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd_11

打开浏览器测试,发送一个空数据是没办法发送的,由于我们没有指定开启那个一个语言脚本文件充当WebSocket 服务器,为我们提供客户端的服务

  Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd技巧_12

指定/home/tinywan/Go/websocket 目录下的 count.sh 作为服务文件,继续测试的结果如下所示

  Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd_13

 Websocket 代理服务器

1、没代理之前访问

var ws = new WebSocket('ws://192.168.18.188:63800');
ws.onopen = function() {
    console.log('CONNECT');
};
ws.onclose = function() {
    console.log('DISCONNECT');
};
ws.onmessage = function(event) {
    console.log('MESSAGE: ' + event.data);
};

2、代理之后访问

var ws = new WebSocket('ws://192.168.18.188:8087/chat/');
ws.onopen = function() {
    console.log('CONNECT');
};
ws.onclose = function() {
    console.log('DISCONNECT');
};
ws.onmessage = function(event) {
    console.log('MESSAGE: ' + event.data);
};

守护进程运行

nohup websocketd --port=63800 /home/www/bin/system_info_send_all_websocketd.sh >/dev/null  2>&1 &

 加载证书

 sudo websocketd --port=6500 --ssl --sslcert="/etc/letsencrypt/live//fullchain.pem" --sslkey="/etc/letsencrypt/live///privkey.pem" /home/www/bin/system_info_send_all_websocketd.s

 wss 协议测试

var ws = new WebSocket('wss://:6500');
ws.onopen = function() {
    console.log('CONNECT');
};
ws.onclose = function() {
    console.log('DISCONNECT');
};
ws.onmessage = function(event) {
    console.log('MESSAGE: ' + event.data);
};

实时监控服务器日志信息

服务端执行脚本执行脚本 

$ websocketd --port=63800 ./system_info_send_all_websocketd.sh 
Sun, 09 Sep 2018 14:34:55 +0800 | INFO   | server     |  | Serving using application   : .../system_info_send_all_websocketd.sh 
Sun, 09 Sep 2018 14:34:55 +0800 | INFO   | server     |  | Starting WebSocket server   : ws://iZ2zec3dge6rwz2uw4tveuZ:63800/
Sun, 09 Sep 2018 14:35:30 +0800 | ACCESS | session    | url:'http://159.110.213.20:63800/websocket/' id:'1536474930878947882' remote:'60.186.221.134' command:'/home/www/bin/system_info_send_all_websocketd.sh' origin:'file://' | CONNECT

本地随便新建以下文件内容

服务器实时日志清空你的浏览器不支持websocket");
                }
            }
            var ws = new WebSocket('ws://www.tinywan.com:63800/websocket/');
            ws.onopen = function (evt) {
                $('.list').append('websocket连接成功');
            }
            ws.onmessage = function (evt) {
                $('.list').append('' + evt.data + '');
                setTimeout(function () {
                    $('#msg').scrollTop($('.list').height() - $('#msg').height());
                }, 100)
            }
            $("#msgBtn").click(function () {
                $(".list").html("");
            })
        });" _ue_custom_node_="true">  

浏览器打开log.html效果:

Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)_websocketd_14

 

Nginx 代理配置

server {
    listen 443 ssl http2;
    server_name ;

    ssl_certificate /etc/letsencrypt//full_chain.pem;
    ssl_certificate_key /etc/letsencrypt//private.key;

    location /wssd
    {
        proxy_pass http://lnmp-php:8888;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_read_timeout 600;

    }
}

连接方式

var ws = new WebSocket('wss:///wssd');

运行一个PHP案例

 

#!/usr/local/php/bin/php
 '127.0.0.1',
    'username' => 'test',
    'password' => 'test',
    'db' => 'test',
    'port' => 3308,
    'prefix' => 'cl_',
    'charset' => 'utf8'
]);

$params = [1, -1];
while (true){
    $users = $db->rawQuery("SELECT count(*) as nums FROM cl_investor WHERE is_order_taking = ? AND ws_online = ?", $params);
    echo json_encode(['counts'=>$users[0]['nums']]). "\n";
    usleep(5000000);
}

 

注意:开头的PHP路径为绝对路径