实现一个使用 Owin 和 SignalR 的 WebSocket API [第 2 部分]






4.60/5 (3投票s)
让我们使用我们在第一部分创建的 API 向用户展示一些统计图表。
引言
我们现在可以接收数据了。
让我们使用 SignalR 将这些信息推送到客户端并在实时图表中显示。
本文是本系列的第二部分。
第一部分可以在这里找到: 创建实时加密货币 WebSocket API [第一部分]。
必备组件
- Visual Studio 2015 或 2017 及 Framework 4.6.1
Coinigy
API 密钥和密钥(请参阅第一部分了解如何获取此密钥和密钥)
目录
- 使用代码
- 步骤 01 - 创建 Web 应用程序
- 步骤 02 - 安装 Nuget 包
- 步骤 03 - 创建 Startup 类
- 步骤 04 - 创建一个 Hub
- 步骤 05 - 订阅事件
- 步骤 06 - 订阅交易频道
- 步骤 07 - 连接并推送交易消息到客户端
- 步骤 08 - 创建一个 HTML 页面
- 步骤 09 - 创建一个 JavaScript 文件
- 步骤 10 - 订阅并更新图表
- 最后的寄语
Using the Code
步骤 01 - 创建 Web 应用程序
打开 Visual Studio,然后转到 文件 > 新建 > 项目,并选择 ASP.NET Web 应用程序。
确保您的框架目标为 .NET Framework 4.6.1。
为您的项目命名(例如:Coinigy.Web
),然后单击“确定”。
选择“Empty”(空)模板,并确保没有其他选项被选中。
单击“确定”。
步骤 02 - 安装 Nuget 包
在程序包管理器控制台中,使用以下命令安装以下程序包:
"Install-Package PureSocketCluster
"
"Install-Package Microsoft.AspNet.SignalR
"
步骤 03 - 创建 Startup 类
我们需要创建一个 OWIN 启动类来初始化 SignalR。
右键单击您的项目,选择“添加 > OWIN Startup 类”,并将其命名为“Startup
”。单击“确定”。
将 Configuration
函数替换为以下代码:
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
步骤 04 - 创建一个 Hub
让我们创建一个 Hubs 文件夹,并添加一个 Hub 来实时向我们的客户端发送信息。
右键单击项目,选择“添加 > 新建文件夹”,并将其命名为“Hubs”。
通过右键单击“Hubs”文件夹并选择“添加 > 新建项 > SignalR Hub 类 (v2)”来添加 Hub,并将其命名为“MarketDataHub
”。
我们仍然需要添加第一部分中 API 的引用,以便在应用程序中使用它。编译第一部分的项目以创建 DLL。通过右键单击 Web 项目下的“引用”节点,选择“添加引用 > 浏览 > 选择第一部分的 DLL > 确定”来添加引用。现在您应该可以在 Web 应用程序中引用该项目了。
让我们回到 MarketDataHub
。
向 Hub 中添加以下字段:
private readonly Websocket socket = null;
并在 Hub 的构造函数中对其进行初始化:
public MarketDataHub()
{
socket = new Websocket(new API.Models.ApiCredentials
{
ApiKey = "[YOUR-API-KEY]",
ApiSecret = "[YOUR-API-SECRET]"
});
}
让我们构建项目,看看一切是否正常。按 Ctrl+Shift+B。
注意:如果您收到以下错误:“已导入具有等效标识的多个程序集…”,请右键单击 Web 项目中“引用”下的 System.Xml.ReaderWriter
并将其删除。重新生成以确保一切正常。
步骤 05 - 订阅事件
现在我们的 WebSocket 已初始化,让我们订阅 OnClientReady
和 OnTradeMessage
事件。
在 Hub 的构造函数中初始化套接字后,添加以下代码:
public MarketDataHub()
{
// Previous code to initialize socket...
this.socket.OnClientReady += Socket_OnClientReady;
this.socket.OnTradeMessage += Socket_OnTradeMessage;
}
并创建适当处理这些事件的函数:
private void Socket_OnClientReady()
{
// Subscribe to a trade channel
}
private void Socket_OnTradeMessage(string exchange, string primaryCurrency, string secondaryCurrency, API.Models.TradeItem trade)
{
// Code to push information to the user
}
正如第一部分所述,这些函数的作用是:当客户端准备好接收命令(准备订阅频道)时收到通知,并在收到新的交易消息时收到通知。
步骤 06 - 订阅交易频道
要订阅交易频道,我们可以将以下代码添加到我们的 Socket_OnClientReady
函数中:
this.socket.SubscribeToTradeChannel("BMEX", "XBT", "USD");
我们现在将在 Socket_OnTradeMessage
函数中接收此交易频道的信息。
步骤 07 - 连接并推送交易消息到客户端
我们只想每秒向用户发送一次更新。我们需要在函数中添加一个 lock
,一次只允许一个线程推送消息。我们还需要添加一个字段来指示是否应等待发送另一条更新。让我们将这两个字段添加到我们的 MarketDataHub
类中:
private readonly object objLock = new object();
private bool doWait = false;
并更新我们的 Socket_OnTradeMessage
函数:
lock (this.objLock)
{
if (this.doWait)
{
Thread.Sleep(1000); // Only send updates once a second
this.doWait = false;
}
Clients.All.broadcastTradePrice(exchange, primaryCurrency, trade.Price);
this.doWait = true;
}
现在,当用户在客户端订阅 broadcastTradePrice
函数时,他们将开始接收更新。
最后,在 Hub 的构造函数中连接好所有事件后,我们需要连接到我们的套接字。在构造函数的末尾添加以下行:
// Initialize socket
// Wire up events
this.socket.Connect();
现在我们的 Hub 已完成。让我们转到客户端。
步骤 08 - 创建一个 HTML 页面
右键单击您的项目,选择“添加 > HTML 页面”,并将其命名为“index.html”。将其内容替换为以下代码:
<!DOCTYPE html>
<html>
<head>
<title>Websocket Example</title>
<!-- Styles -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/epoch/0.8.4/css/epoch.min.css" />
</head>
<body>
<h1> Gauge: </h1>
<div id="gaugeChart" class="epoch gauge-small"></div>
<h1> Area chart: </h1>
<div id="areaChart" class="epoch" style="width: 100%; height: 300px;border:solid 1px #C0C0C0;"></div>
<h1> Line chart: </h1>
<div id="lineChart" class="epoch" style="width: 100%; height: 300px;border:solid 1px #C0C0C0;"></div>
<!-- Scripts -->
<script src="Scripts/jquery-1.6.4.min.js"></script>
<script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
<script src="signalr/hubs"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/epoch/0.8.4/js/epoch.min.js"></script>
<script src="Scripts/scripts.js"></script>
</body>
</html>
此页面将显示一个折线图、面积图和仪表盘图。
步骤 09 - 创建一个 JavaScript 文件
让我们添加一些 JavaScript 来订阅来自服务器的事件。
右键单击“Scripts”文件夹,选择“添加 > JavaScript 文件”,并将其命名为“scripts.js”。
我们可以通过在我们的脚本文件中使用以下代码来开始初始化我们的图表:
$(function () {
// Declare area chart
var areaChart = $('#areaChart').epoch({
type: 'time.area',
data: [{ values: [] }],
axes: ['left', 'bottom', 'right']
});
// Declare line chart
var lineChart = $('#lineChart').epoch({
type: 'time.line',
data: [{ values: [] }],
axes: ['left', 'bottom', 'right']
});
// Declare gauge chart
var gaugeChart = $('#gaugeChart').epoch({
type: 'time.gauge',
value: previousPrice
});
// Add some code here to subscribe to the server's events
});
现在我们可以订阅我们创建的 SignalR Hub。在初始化图表后,将以下 3 个字段添加到脚本中:
// Declare a proxy to reference the hub.
var marketDataHub = $.connection.marketDataHub;
// Get a time stamp
var timestamp = ((new Date()).getTime() / 1000) | 0;
var previousPrice = 0;
timestamp
字段将用于跟踪图表 x 轴上的时间。y 轴将显示交易市场价格。
previousPrice
字段由我们的仪表盘图使用。我们使用此值来确定市场数据的平均价格涨跌。(仪表盘图以百分比显示其值。)
步骤 10 - 订阅并更新图表
一切都已设置完毕,我们可以开始监听从服务器发送的消息。让我们将以下函数添加到我们的脚本文件中:
// This invoked from the server side in the MarketDataHub.cs file
marketDataHub.client.broadcastTradePrice = function (exchange, primaryCurrency, price) {
// Update the area chart
areaChart.push([{ time: timestamp, y: price }]);
// Update the line chart
lineChart.push([{ time: timestamp, y: price }]);
// If the previous price has not been initialized, make the previous price the current price.
previousPrice = previousPrice == 0 ? price : previousPrice;
// Calculate performance
var performance = price / previousPrice;
// Update the gauge chart
gaugeChart.update(performance);
// Increase time stamp
timestamp++;
console.log(price);
previousPrice = price;
};
折线图和面积图的参数是 timestamp
和 y
。时间显示在 x 轴上,价格显示在 y 轴上。
接下来,我们进行计算以确定百分比涨跌以更新我们的仪表盘图。在所有图表更新后,我们增加 timestamp
并等待服务器发送下一条消息。最后,我们可以启动与 Hub 的连接。在上述函数之后添加以下代码:
// Start the connection to the market hub
$.connection.hub.start();
按 F5 调试您的 Web 应用程序。您应该看到图表实时更新。
结束语
我们现在可以在 Web 应用程序中使用我们的 API,以可视化的图表形式向用户显示实时交易市场数据。