HTML5-WebSocket实现对服务器CPU实时监控
由于WebSocket允许保持长连接,因此当建立连接后服务器可以主动地向Client发送相关信息.下面通过服务端获取当前CPU的使用情况主动发送给网页,让网页实时显示CPU使用情况的曲线图.该事例的主要功能是包括服务端获取CPU使和情况和HTML5使用canvas进行曲线图绘制.
应用效果
实现效果主要是模仿windows的任务管理器,显示每个核的工作情况.
C#获取CPU使用情况
可能通过PerformanceCounter来获取具本CPU线程的使用情况,不过在构建PerformanceCounter前先获取到CPU对应的线程数量.获取这个数量可以通过Environment.ProcessorCount属性获取,然后遍历构建每个PerformanceCounter
1 2 3 4 5 | int coreCount = Environment.ProcessorCount; for ( int i = 0; i < coreCount; i++) { mCounters.Add( new PerformanceCounter( "Processor" , "% Processor Time" , i.ToString())); } |
为了方便计数器的处理,简单地封装了一个基础类,完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | /// <summary> /// Copyright © henryfan 2012 ///Email: henryfan@msn.com ///HomePage: http://www.ikende.com ///CreateTime: 2012/12/24 15:10:44 /// </summary> public class ProcessorCounter { private List<PerformanceCounter> mCounters = new List<PerformanceCounter>(); public IList<PerformanceCounter> Counters { get { return mCounters; } } public void Open() { int coreCount = Environment.ProcessorCount; for ( int i = 0; i < coreCount; i++) { mCounters.Add( new PerformanceCounter( "Processor" , "% Processor Time" , i.ToString())); } } public ItemUsage[] GetValues() { ItemUsage[] values = new ItemUsage[mCounters.Count]; for ( int i = 0; i < mCounters.Count; i++) { values[i] = new ItemUsage(); values[i].ID = i.ToString(); values[i].Name = "CPU " +i.ToString(); values[i].Percent = mCounters[i].NextValue(); } return values; } } public class ItemUsage { public string Name { get ; set ; } public float Percent { get ; set ; } public string ID { get ; set ; } } |
这样一个用于统计CPU所有线程使用情况计数的类就完成了.
页面绘制处理
首先定义一些简单的处理结构
1 2 3 4 5 6 7 8 9 10 11 | function ProcessorInfo() { this .Item = null ; this .Points = new Array(); for ( var i = 0; i < 50; i++) { this .Points.push( new Point(0, 0)); } } function Point(x, y) { this .X = x; this .Y = y; } |
主要定义线程信息结构,默认初始化50个座标,当在接收服务线程使用情况的时候,构建一个点添加到数组件尾部同时把第一个移走.通过定时绘制这50个点的曲线这样一个动态的走势就可以完成了.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | function drawProceessor(item) { var canvas = document.getElementById( 'processimg' + item.Item.ID); var context = canvas.getContext( '2d' ); context.beginPath(); context.rect(0, 0, 200, 110); context.fillStyle = 'black' ; context.fill(); context.lineWidth = 2; context.strokeStyle = 'white' ; context.stroke(); context.beginPath(); context.moveTo(2, 106); for ( var i = 0; i < item.Points.length; i++) { context.lineTo(4 * i + 2, 110 - item.Points[i].Y - 4); } context.lineTo(200, 106); context.closePath(); context.lineWidth = 1; context.fillStyle = '#7FFF00' ; context.fill(); context.strokeStyle = '#7CFC00' ; context.stroke(); context.font = '12pt Calibri' ; context.fillStyle = 'white' ; context.fillText(item.Item.Name, 60, 20); } function addUploadItem(info) { if (cpus[info.ID] == null ) { var pinfo = new ProcessorInfo(); pinfo.Item = info; $( '<canvas id="processimg' + info.ID + '" width="200" height="110"></canvas>' ).appendTo($( '#lstProcessors' )); cpus[info.ID] = pinfo; processors.push(pinfo); pinfo.Points.shift(); pinfo.Points.push( new Point(0, info.Percent)); drawProceessor(pinfo); } else { var pinfo = cpus[info.ID]; pinfo.Points.shift(); pinfo.Points.push( new Point(0, info.Percent)); } } |
只需要通过定时器来不停地更新线程使用绘制即可.
1 2 3 4 5 | setInterval( function () { for ( var i = 0; i < processors.length; i++) { drawProceessor(processors[i]); } }, 1000); |
服务端
对于服务端其实可以根据自己的需要来使用websocket协议实现,.net 4.5也提供相应的封装.而这里则使用了beetle对应websocket的扩展协议包,整体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | class Program : WebSocketJsonServer { static void Main( string [] args) { TcpUtils.Setup( "beetle" ); Program server = new Program(); server.Open(8070); Console.WriteLine( "websocket start@8070" ); ProcessorCounter counters = new ProcessorCounter(); counters.Open(); while ( true ) { ItemUsage[] items = counters.GetValues(); foreach (ItemUsage item in items) { Console.WriteLine( "{0}:{1}%" , item.Name, item.Percent); } JsonMessage message = new JsonMessage(); message.type = "cpu useage" ; message.data = items; foreach (TcpChannel channel in server.Server.GetOnlines()) { channel.Send(message); } System.Threading.Thread.Sleep(995); } System.Threading.Thread.Sleep(-1); } protected override void OnError( object sender, ChannelErrorEventArgs e) { base .OnError(sender, e); Console.WriteLine(e.Exception.Message); } protected override void OnConnected( object sender, ChannelEventArgs e) { base .OnConnected(sender, e); Console.WriteLine( "{0} connected" , e.Channel.EndPoint); } protected override void OnDisposed( object sender, ChannelDisposedEventArgs e) { base .OnDisposed(sender, e); Console.WriteLine( "{0} disposed" , e.Channel.EndPoint); } } |
每秒获取一次CPU的使用情况,并把信息以json的方式发送给当前所有在线的连接.
下载
完整代码:ProcessorsMonitor.rar (686.02 kb)
演示地址:http://html5.ikende.com/ProcessorsMonitor.htm (浏览器使用chrome或IE10)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架