版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010136741/article/details/51581298
转载请标明出处:http://blog.csdn.net/u010136741/article/details/51581298, 本文出自: 柳木木_kylin
【总目录】
【实例简介】
前面我们已经介绍了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);
}
});
});
【演示地址】
电脑访问:
手机浏览器、微信访问:
【源码下载】
【结束语】
在写这篇文章的时候,我发现了这个demo存在的一个性能隐患,有没读者也发现了这个问题,欢迎留言吐槽!