【实例简介】
前面我们已经介绍了WebSocket的概念和WebSocket的Api,下面我们通过一个简单的实例,来实际体验一下WebSocket。
下面,我们要展示的是一个实时获取服务器内存使用情况的一个案例。用户打开页面,通过websocket连接到服务器,服务器每隔一秒钟,会返回服务器内存的使用情况,达到对内存的实时监控,作为运维人员来说,可以通过微信,手机浏览器等实现对服务器状态的实时监听。
【客户端】
首先,我们需要设计一个简单的页面,页面主要包含一个表格,表格会列出内存的总容量、正在使用的内存、闲置的内存、以及写缓存和读缓存。
我们先看看客户端的头部,再来讲解思路:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>WebSocket入门教程(三)-- WebSocket实例:实时获取服务器内存使用情况</title>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.css">
- <link rel="stylesheet" href="http://cdn.bootcss.com/tether/1.3.2/css/tether.css"/>
- <script src="http://cdn.bootcss.com/jquery/2.2.4/jquery.js" ></script>
- <script src="http://cdn.bootcss.com/tether/1.3.2/js/tether.js"></script>
- <script src="http://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/js/bootstrap.js"></script>
- <script>
- // code from chapter goes here
- $(function() {
- //alert("xxx");
- var ws = new WebSocket("ws://www.liumumu.top:8181");
- var mem = {"total": 0,
- "used": 0,
- "free": 0,
- "buffers": 0,
- "cached": 0};
- ws.onopen = function(e){
- console.log("Connection established");
- };
- var changeMemEntry = function(field,originalValue,newValue){
- var valElem = $('#' + field + ' span');
- valElem.html(newValue);
- if(originalValue == 0){
- return;
- }
- if(field =="free"){
- if(newValue < originalValue){
- valElem.addClass('label-danger');
- valElem.removeClass('label-success');
- }else if(newValue>originalValue){
- valElem.addClass('label-success');
- valElem.removeClass('label-danger');
- }
- }else{
- if(newValue > originalValue){
- valElem.addClass('label-danger');
- valElem.removeClass('label-success');
- }else if(newValue<originalValue){
- valElem.addClass('label-success');
- valElem.removeClass('label-danger');
- }
- }
- }
- ws.onmessage = function(e){
- var memData = JSON.parse(e.data);
- //console.log("onmessage",memData);
- for(var field in memData){
- if(memData.hasOwnProperty(field)){
- changeMemEntry(field,mem[field],memData[field]);
- mem[field] = memData[field];
- }
- }
- }
- ws.onerror = function(e){
- console.log("WebSocket failure,error",e);
- //handleErrors(e);
- }
- ws.onclose = function(e){
- console.log(e);
- console.log(e.reason+" "+e.code);
- for(var field in mem){
- if(mem.hasOwnProperty(field)){
- mem[field] = 0;
- }
- }
- }
- });
- </script>
- <style>
- html,body{
- height:100%;
- }
- </style>
- </head>
- <body lang="cn">
- <div class="vertical-center">
- <div class="container">
- <h1 style="text-align:center;padding:5px;">柳木木ECS概况</h1>
- <table class="table" id="memTable">
- <thead>
- <tr>
- <th>类型</th>
- <th>大小(KB)</th>
- </tr>
- </thead>
- <tbody id="memRows">
- <tr>
- <td><h3>内存总量</h3></td>
- <td id="total">
- <h3><span class="label label-default label-success">0.00</span></h3>
- </td>
- </tr>
- <tr>
- <td><h3>已使用内存</h3></td>
- <td id="used">
- <h3><span class="label label-default label-success">0.00</span></h3>
- </td>
- </tr>
- <tr>
- <td><h3>闲置内存</h3></td>
- <td id="free">
- <h3><span class="label label-default label-success">0.00</span></h3>
- </td>
- </tr>
- <tr>
- <td><h3>写缓存</h3></td>
- <td id="buffers">
- <h3><span class="label label-default label-success">0.00</span></h3>
- </td>
- </tr>
- <tr>
- <td><h3>读缓存</h3></td>
- <td id="cached">
- <h3><span class="label label-default label-success">0.00</span></h3>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- </div>
- </body>
- </html>
首先我们连接服务器,然后给每个字段附上初始值0,定义了changeMemEntry用来更新页面的数据和样式。
在onmessage回调方法里,我们将接收到的json字符串解析成json对象,然后遍历对象的每个属性,将属性值传递给changeMemEntry,实现数据的更新。在onclose回调方法里,我们将数据清0。
页面的展示效果如下图:
【服务器端】
本案例服务器端,我们通过nodejs实现,大体步骤如下
1.创建websocket服务,监听8181端口。
2.当客户端请求连接并且连接成功时,运行linux的free命令,获取内存信息,通过正则将标准输出字符串,转换成json对象,然后返回给客户端。
3.开始定时器,每一秒钟执行循环第2步操作。
4.当连接关闭时,清除定时器。
- //send memory info per seconds
- var WebSocketServer = require('ws').Server,
- wss = new WebSocketServer({port:8181});
- var spawn = require('child_process').spawn;
- function sendMemInfo(ws){
- var free = spawn('free',['-k']);
- free.stdout.on('data',function(data){
- var strdata = ""+data;
- //console.log(strdata);
- //正则匹配,获取数据
- var re = /Mem: *(\d*) *(\d*) *(\d*) *(\d*) *(\d*) *(\d*)/;
- var result = strdata.match(re);
- var mem = {};
- if(result.length>0){
- mem["total"] = parseInt(result[1]);
- mem["used"] = parseInt(result[2]);
- mem["free"] = parseInt(result[3]);
- //mem["shared"] = parseInt(result[4]);
- mem["buffers"] = parseInt(result[5]);
- mem["cached"] = parseInt(result[6]);
- ws.send(JSON.stringify(mem));
- }
- });
- }
- wss.on('connection',function(ws){
- var clientMemUpdater;
- var sendMemUpdates = function(ws){
- if(ws.readyState == 1){
- sendMemInfo(ws);
- }
- }
- clientMemUpdater = setInterval(function(){
- sendMemUpdates(ws);
- },1000);
- var clientStocks = [];
- sendMemUpdates(ws);
- ws.on("close",function(){
- if(typeof clientMemUpdater != 'undefined'){
- clearInterval(clientMemUpdater);
- }
- });
- });