由于WebSocket允許保持長(zhǎng)連接,因此當(dāng)建立連接后服務(wù)器可以主動(dòng)地向Client發(fā)送相關(guān)信息.下面通過(guò)服務(wù)端獲取當(dāng)前CPU的使用情況主動(dòng)發(fā)送給網(wǎng)頁(yè),讓網(wǎng)頁(yè)實(shí)時(shí)顯示CPU使用情況的曲線圖.該事例的主要功能是包括服務(wù)端獲取CPU使和情況和HTML5使用canvas進(jìn)行曲線圖繪制.
應(yīng)用效果
實(shí)現(xiàn)效果主要是模仿windows的任務(wù)管理器,顯示每個(gè)核的工作情況.
C#獲取CPU使用情況
可能通過(guò)PerformanceCounter來(lái)獲取具本CPU線程的使用情況,不過(guò)在構(gòu)建PerformanceCounter前先獲取到CPU對(duì)應(yīng)的線程數(shù)量.獲取這個(gè)數(shù)量可以通過(guò)Environment.ProcessorCount屬性獲取,然后遍歷構(gòu)建每個(gè)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())); } |
為了方便計(jì)數(shù)器的處理,簡(jiǎn)單地封裝了一個(gè)基礎(chǔ)類,完整代碼如下:
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 ; } } |
這樣一個(gè)用于統(tǒng)計(jì)CPU所有線程使用情況計(jì)數(shù)的類就完成了.
頁(yè)面繪制處理
首先定義一些簡(jiǎn)單的處理結(jié)構(gòu)
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; } |
主要定義線程信息結(jié)構(gòu),默認(rèn)初始化50個(gè)座標(biāo),當(dāng)在接收服務(wù)線程使用情況的時(shí)候,構(gòu)建一個(gè)點(diǎn)添加到數(shù)組件尾部同時(shí)把第一個(gè)移走.通過(guò)定時(shí)繪制這50個(gè)點(diǎn)的曲線這樣一個(gè)動(dòng)態(tài)的走勢(shì)就可以完成了.
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)); } } |
只需要通過(guò)定時(shí)器來(lái)不停地更新線程使用繪制即可.
1
2
3
4
5 |
setInterval( function
() { for
( var i = 0; i < processors.length; i++) { drawProceessor(processors[i]); } }, 1000); |
服務(wù)端
對(duì)于服務(wù)端其實(shí)可以根據(jù)自己的需要來(lái)使用websocket協(xié)議實(shí)現(xiàn),.net 4.5也提供相應(yīng)的封裝.而這里則使用了beetle對(duì)應(yīng)websocket的擴(kuò)展協(xié)議包,整體代碼如下:
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的方式發(fā)送給當(dāng)前所有在線的連接.
下載
完整代碼:ProcessorsMonitor.rar (686.02 kb)
演示地址:http://html5.ikende.com/ProcessorsMonitor.htm (瀏覽器使用chrome或IE10)
via:http://www.cnblogs.com/smark/archive/2012/12/25/2833129.html