65.9K
CodeProject 正在变化。 阅读更多。
Home

HTML5:来自 .NET 应用程序的实时推送通知

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (32投票s)

2014年5月5日

CPOL

3分钟阅读

viewsIcon

103036

downloadIcon

3419

用于 HTML5 JavaScript 和 .NET 之间发布-订阅场景的简单示例,使用 Websockets。

引言

下面的示例演示了 JavaScript 和 .NET 应用程序之间的发布-订阅通信场景。 HTML5 JavaScript 客户端需要订阅 .NET 应用程序中的一个或多个事件。 当事件发生时,.NET 应用程序会通知已订阅的客户端。

该通信通过 WebSockets(全双工单套接字连接)实现,因此它不使用 HTTP 协议情况下的轮询或长轮询机制。

当事件发生时,通知消息会立即从服务推送到所有已订阅的客户端。

示例代码

示例应用程序基于 Eneter.Messaging.Framework,这是一个免费的轻量级跨平台框架,用于进程间通信,非常易于使用。
该示例还使用了 Chart.js library。 一个用于绘制图表的优秀的免费库。

运行示例

  • 下载并解压此示例。
  • http://www.eneter.net/ProductDownload.htm 下载适用于 .NET 的 Eneter。
  • 从 http://www.eneter.net/ProductDownload.htm 下载适用于 Javascript 的 Eneter。
  • 将适用于 Javascript 的 Eneter 复制到 CpuUsageClient 目录中。
  • 在编辑器中打开 index.html 文件,并确保它使用的 eneter-messaging 版本与您下载的版本相同。
  • 在 Visual Studio 中打开示例项目,并将对您下载的 Eneter.Messaging.Framework.dll 的引用添加到项目中。
  • 构建应用程序并执行它。
  • 在互联网浏览器中打开 index.html(来自 CpuUsageClient 目录)。
  • 按“打开连接”按钮,然后按“订阅”按钮。
  • 网页开始获取通知并显示图表。

为了演示 JavaScript 和 .NET 之间的发布-订阅场景,下面的示例实现了一个简单的 .NET 控制台应用程序和一个简单的 HTML5 网页。
控制台应用程序定期检查 CPU 使用率并通知其值。
HTML5 网页订阅以接收 CPU 使用率的通知。 收到通知后,它会更新该值并显示图表。

768473/PublishSubscribeBetweenJSNET.png

使用双工代理

该示例的主要思想是使用 Eneter Messaging Framework 中的双工代理组件。 它提供了发送通知事件(发布)以及订阅所需事件的功能。
当代理收到通知消息时,它会将该消息转发给所有对此类通知感兴趣的订阅者。
Eneter 框架的跨平台方面确保了 JavaScript 和 .NET 之间的消息能够被理解(例如,它处理 UTF16 与 UTF8 或小端与大端)。

.NET 服务应用程序

服务应用程序是一个简单的 .NET 控制台应用程序,它定期检查 CPU 使用率。 然后,它使用代理组件发布该值。 代理搜索哪些客户端订阅了这种类型的事件,并将消息转发给它们。

此外,由于 JavaScript 使用 JSON 序列化程序,因此该服务也使用 JSON 序列化程序。 它还将双工代理设置为使用 JSON 序列化程序。

整个实现非常简单

using System;
using System.Diagnostics;
using System.Threading;
using Eneter.Messaging.DataProcessing.Serializing;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.WebSocketMessagingSystem;
using Eneter.Messaging.Nodes.Broker;

namespace CpuUsageService
{
    // Message that will be notified.
    public class CpuUpdateMessage
    {
        public float Usage { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // JavaScript uses JSON serializer so set using JSON.
            ISerializer aSerializer = new DataContractJsonStringSerializer();

            // Create broker.
            IDuplexBrokerFactory aBrokerFactory = new DuplexBrokerFactory();
            IDuplexBroker aBroker = aBrokerFactory.CreateBroker();

            // Communicate using WebSockets.
            IMessagingSystemFactory aMessaging = new WebSocketMessagingSystemFactory();
            IDuplexInputChannel anInputChannel = 
               aMessaging.CreateDuplexInputChannel("ws://127.0.0.1:8843/CpuUsage/");

            anInputChannel.ResponseReceiverConnected += (x, y) =>
            {
                Console.WriteLine("Connected client: " + y.ResponseReceiverId);
            };
            anInputChannel.ResponseReceiverDisconnected += (x, y) =>
            {
                Console.WriteLine("Disconnected client: " + y.ResponseReceiverId);
            };

            // Attach input channel and start listeing.
            aBroker.AttachDuplexInputChannel(anInputChannel);

            // Start working thread monitoring the CPU usage.
            bool aStopWorkingThreadFlag = false;
            Thread aWorkingThread = new Thread(() =>
                {
                    PerformanceCounter aCpuCounter =
                      new PerformanceCounter("Processor", "% Processor Time", "_Total");

                    while (!aStopWorkingThreadFlag)
                    {
                        CpuUpdateMessage aMessage = new CpuUpdateMessage();
                        aMessage.Usage = aCpuCounter.NextValue();

                        //Console.WriteLine(aMessage.Usage);

                        // Serialize the message.
                        object aSerializedMessage =
                           aSerializer.Serialize<CpuUpdateMessage>(aMessage);

                        // Notify subscribers via the broker.
                        // Note: The broker will forward the message to subscribed clients.
                        aBroker.SendMessage("MyCpuUpdate", aSerializedMessage);

                        Thread.Sleep(500);
                    }
                });
            aWorkingThread.Start();

            Console.WriteLine("CpuUsageService is running press ENTER to stop.");
            Console.ReadLine();

            // Wait until the working thread stops.
            aStopWorkingThreadFlag = true;
            aWorkingThread.Join(3000);

            // Detach the input channel and stop listening.
            aBroker.DetachDuplexInputChannel();
        }
    }
}

JavaScript 客户端

JavaScript 客户端是一个简单的 HTML 5 网页,它使用双工代理客户端组件来订阅 CPU 使用率通知。 收到通知消息后,它会更新显示值的图表。 随着收到新的通知值,图表会移动。

整个实现非常简单

<!DOCTYPE html>
<html>
    <head>
        <title>CPU Usage Client</title>
        
        <script src="Chart.js"></script>

        <!- ENSURE HERE IS THE SAME ENETER VERSION AS YOU DOWNLOADED -->
        <script src="eneter-messaging-6.5.0.js"></script>

        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body onunload="closeConnection();">
        <div>
            <button type="button" onclick="openConnection();">1. Open Connection</button>
        </div>
        <div>
            <button type="button" onclick="subscribe();">2. Subscribe</button>
            <button type="button" onclick="unsubscribe();">3. Unsubscribe</button>
        </div>
        <div>
            <button type="button" onclick="closeConnection();">4. Close Connection</button>
        </div>
        <div>
            <canvas id="canvas" height="300" width="300"></canvas>
        </div>
        
        <script>
            // Initialize chart.
            var myChartConfig = {
                        animation : false,
                        scaleOverlay : true,
                        scaleOverride : true,
                    scaleSteps : 10,
                        scaleStepWidth : 10,
                        scaleStartValue : 0
            };
            var myLineChartData = {
            labels : ["", "", "", "", "", "", "", "", "", ""],
            datasets : [
                {
                    fillColor : "rgba(220,220,220,0.5)",
                    strokeColor : "rgba(220,220,220,1)",
                    pointColor : "rgba(220,220,220,1)",
                    pointStrokeColor : "#fff",
                    data : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
                }
            ]
            
        };
            var myChart = new Chart(document.getElementById("canvas").getContext("2d"));
            
            // Create the duplex output channel.
            var myOutputChannel =
              new WebSocketDuplexOutputChannel("ws://127.0.0.1:8843/CpuUsage/", null);

            // Create BrokerClient
            var myBrokerClient = new DuplexBrokerClient();
            
            // Subscribe to notifications.
            myBrokerClient.onBrokerMessageReceived = onBrokerMessageReceived;
            
            function openConnection() {
                // Attach output channel and be able to send messages and receive responses.
                myBrokerClient.attachDuplexOutputChannel(myOutputChannel);
            };

            function closeConnection() {
                // Detach output channel and stop listening to responses.
                myBrokerClient.detachDuplexOutputChannel();
            };

            function subscribe() {
                myBrokerClient.subscribe("MyCpuUpdate");
            };

            function unsubscribe() {
                myBrokerClient.unsubscribe("MyCpuUpdate");
            };
            
            function onBrokerMessageReceived(brokerMessageReceivedEventArgs) {
                // If the notified message is the CPU status update.
                if (brokerMessageReceivedEventArgs.MessageTypeId === "MyCpuUpdate")
                {
                    // Deserialize notified message content.
                    var aValue = JSON.parse(brokerMessageReceivedEventArgs.Message);
                    
                    // Update data and draw the chart.
                    myLineChartData.datasets[0].data.shift();
                    myLineChartData.datasets[0].data.push(aValue.Usage);
                    myChart.Line(myLineChartData, myChartConfig);
                }
            };
        </script>
    </body>
</html>
© . All rights reserved.