您的位置:首页 > 编程语言 > ASP

ASP.NET SignalR-Server Broadcast with SignalR

2016-09-11 15:04 162 查看
服务端通知表示发送到客户端的消息是由服务端发起的,这种情景与由一个客户端发出消息并通知其他所有客户端的情景不同。

创建一个股票报价机应用程序,由服务器端收集股票走势信息,并通知所有连接到服务端的客户端:

Stock.cs:

namespace SignalR.StockTicker
{
public class Stock
{
private decimal _price;

public string Symbol { get; set; }

public decimal Price
{
get
{
return _price;
}
set
{
if (_price == value)
{
return;
}

_price = value;

if (DayOpen == 0)
{
DayOpen = _price;
}
}
}

public decimal DayOpen { get; private set; }

public decimal Change
{
get
{
return Price - DayOpen;
}
}

public double PercentChange
{
get
{
return (double)Math.Round(Change / Price, 4);
}
}
}
}

StockTickerHub.cs:
namespace SignalR.StockTicker
{
[HubName("stockTickerMini")]
public class StockTickerHub : Hub
{
private readonly StockTicker _stockTicker;

public StockTickerHub() : this(StockTicker.Instance) { }

public StockTickerHub(StockTicker stockTicker)
{
_stockTicker = stockTicker;
}

public IEnumerable<Stock> GetAllStocks()
{
return _stockTicker.GetAllStocks();
}
}
}

StockTicker.cs:
<span></span><pre style="" class="prettyprint prettyprinted"><span class="pln">
</span><span class="kwd">namespace</span><span class="pln"> </span><span class="typ">SignalR</span><span class="pun">.</span><span class="typ">StockTicker</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">class</span><span class="pln"> </span><span class="typ">StockTicker</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">// Singleton instance</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">Lazy</span><span class="pun"><</span><span class="typ">StockTicker</span><span class="pun">></span><span class="pln"> _instance </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Lazy</span><span class="pun"><</span><span class="typ">StockTicker</span><span class="pun">>(()</span><span class="pln"> </span><span class="pun">=></span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">StockTicker</span><span class="pun">(</span><span class="typ">GlobalHost</span><span class="pun">.</span><span class="typ">ConnectionManager</span><span class="pun">.</span><span class="typ">GetHubContext</span><span class="pun"><</span><span class="typ">StockTickerHub</span><span class="pun">>().</span><span class="typ">Clients</span><span class="pun">));</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="typ">ConcurrentDictionary</span><span class="pun"><</span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Stock</span><span class="pun">></span><span class="pln"> _stocks </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">ConcurrentDictionary</span><span class="pun"><</span><span class="kwd">string</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Stock</span><span class="pun">>();</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="kwd">object</span><span class="pln"> _updateStockPricesLock </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="kwd">object</span><span class="pun">();</span><span class="pln">

</span><span class="com">//stock can go up or down by a percentage of this factor on each change</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="kwd">double</span><span class="pln"> _rangePercent </span><span class="pun">=</span><span class="pln"> </span><span class="pun">.</span><span class="lit">002</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="typ">TimeSpan</span><span class="pln"> _updateInterval </span><span class="pun">=</span><span class="pln"> </span><span class="typ">TimeSpan</span><span class="pun">.</span><span class="typ">FromMilliseconds</span><span class="pun">(</span><span class="lit">250</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="typ">Random</span><span class="pln"> _updateOrNotRandom </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">();</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">readonly</span><span class="pln"> </span><span class="typ">Timer</span><span class="pln"> _timer</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">volatile</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> _updatingStockPrices </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="typ">StockTicker</span><span class="pun">(</span><span class="typ">IHubConnectionContext</span><span class="str"><dynamic></span><span class="pln"> clients</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">Clients</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> clients</span><span class="pun">;</span><span class="pln">

_stocks</span><span class="pun">.</span><span class="typ">Clear</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> stocks </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">List</span><span class="pun"><</span><span class="typ">Stock</span><span class="pun">></span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Stock</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"MSFT"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Price</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">30.31m</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Stock</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"APPL"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Price</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">578.18m</span><span class="pln"> </span><span class="pun">},</span><span class="pln">
</span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Stock</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="typ">Symbol</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="str">"GOOG"</span><span class="pun">,</span><span class="pln"> </span><span class="typ">Price</span><span class="pln"> </span><span class="pun">=</span><span class="pln"> </span><span class="lit">570.30m</span><span class="pln"> </span><span class="pun">}</span><span class="pln">
</span><span class="pun">};</span><span class="pln">
stocks</span><span class="pun">.</span><span class="typ">ForEach</span><span class="pun">(</span><span class="pln">stock </span><span class="pun">=></span><span class="pln"> _stocks</span><span class="pun">.</span><span class="typ">TryAdd</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">.</span><span class="typ">Symbol</span><span class="pun">,</span><span class="pln"> stock</span><span class="pun">));</span><span class="pln">

_timer </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Timer</span><span class="pun">(</span><span class="typ">UpdateStockPrices</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">null</span><span class="pun">,</span><span class="pln"> _updateInterval</span><span class="pun">,</span><span class="pln"> _updateInterval</span><span class="pun">);</span><span class="pln">

</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="kwd">static</span><span class="pln"> </span><span class="typ">StockTicker</span><span class="pln"> </span><span class="typ">Instance</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">get</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> _instance</span><span class="pun">.</span><span class="typ">Value</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="typ">IHubConnectionContext</span><span class="str"><dynamic></span><span class="pln"> </span><span class="typ">Clients</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">get</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">set</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">public</span><span class="pln"> </span><span class="typ">IEnumerable</span><span class="pun"><</span><span class="typ">Stock</span><span class="pun">></span><span class="pln"> </span><span class="typ">GetAllStocks</span><span class="pun">()</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> _stocks</span><span class="pun">.</span><span class="typ">Values</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">UpdateStockPrices</span><span class="pun">(</span><span class="kwd">object</span><span class="pln"> state</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">lock</span><span class="pln"> </span><span class="pun">(</span><span class="pln">_updateStockPricesLock</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">_updatingStockPrices</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
_updatingStockPrices </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">

</span><span class="kwd">foreach</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">var</span><span class="pln"> stock </span><span class="kwd">in</span><span class="pln"> _stocks</span><span class="pun">.</span><span class="typ">Values</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">TryUpdateStockPrice</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">BroadcastStockPrice</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

_updatingStockPrices </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">bool</span><span class="pln"> </span><span class="typ">TryUpdateStockPrice</span><span class="pun">(</span><span class="typ">Stock</span><span class="pln"> stock</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">// Randomly choose whether to update this stock or not</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> r </span><span class="pun">=</span><span class="pln"> _updateOrNotRandom</span><span class="pun">.</span><span class="typ">NextDouble</span><span class="pun">();</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">r </span><span class="pun">></span><span class="pln"> </span><span class="pun">.</span><span class="lit">1</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="com">// Update the stock price by a random factor of the range percent</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> random </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">new</span><span class="pln"> </span><span class="typ">Random</span><span class="pun">((</span><span class="kwd">int</span><span class="pun">)</span><span class="typ">Math</span><span class="pun">.</span><span class="typ">Floor</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">.</span><span class="typ">Price</span><span class="pun">));</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> percentChange </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="typ">NextDouble</span><span class="pun">()</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> _rangePercent</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> pos </span><span class="pun">=</span><span class="pln"> random</span><span class="pun">.</span><span class="typ">NextDouble</span><span class="pun">()</span><span class="pln"> </span><span class="pun">></span><span class="pln"> </span><span class="pun">.</span><span class="lit">51</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">var</span><span class="pln"> change </span><span class="pun">=</span><span class="pln"> </span><span class="typ">Math</span><span class="pun">.</span><span class="typ">Round</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">.</span><span class="typ">Price</span><span class="pln"> </span><span class="pun">*</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">decimal</span><span class="pun">)</span><span class="pln">percentChange</span><span class="pun">,</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln">
change </span><span class="pun">=</span><span class="pln"> pos </span><span class="pun">?</span><span class="pln"> change </span><span class="pun">:</span><span class="pln"> </span><span class="pun">-</span><span class="pln">change</span><span class="pun">;</span><span class="pln">

stock</span><span class="pun">.</span><span class="typ">Price</span><span class="pln"> </span><span class="pun">+=</span><span class="pln"> change</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="kwd">private</span><span class="pln"> </span><span class="kwd">void</span><span class="pln"> </span><span class="typ">BroadcastStockPrice</span><span class="pun">(</span><span class="typ">Stock</span><span class="pln"> stock</span><span class="pun">)</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="typ">Clients</span><span class="pun">.</span><span class="typ">All</span><span class="pun">.</span><span class="pln">updateStockPrice</span><span class="pun">(</span><span class="pln">stock</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">

</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span>

startup.cs:

public class Startup
{
public void Configuration(IAppBuilder app)
{
// Any connection or hub wire up and configuration should go here
app.MapSignalR();
}

}html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ASP.NET SignalR Stock Ticker</title>
<style>
body {
font-family: 'Segoe UI', Arial, Helvetica, sans-serif;
font-size: 16px;
}
#stockTable table {
border-collapse: collapse;
}
#stockTable table th, #stockTable table td {
padding: 2px 6px;
}
#stockTable table td {
text-align: right;
}
#stockTable .loading td {
text-align: left;
}
</style>
</head>
<body>
<h1>ASP.NET SignalR Stock Ticker Sample</h1>

<h2>Live Stock Table</h2>
<div id="stockTable">
<table border="1">
<thead>
<tr><th>Symbol</th><th>Price</th><th>Open</th><th>Change</th><th>%</th></tr>
</thead>
<tbody>
<tr class="loading"><td colspan="5">loading...</td></tr>
</tbody>
</table>
</div>

<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="/Scripts/jquery-1.10.2.min.js" ></script>
<!--Reference the SignalR library. -->
<script src="/Scripts/jquery.signalR-2.1.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<!--Reference the StockTicker script. -->
<script src="StockTicker.js"></script>
</body>
</html>js:
// A simple templating method for replacing placeholders enclosed in curly braces.
if (!String.prototype.supplant) {
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
}

$(function () {

var ticker = $.connection.stockTickerMini, // the generated client-side hub proxy
up = '▲',
down = '▼',
$stockTable = $('#stockTable'),
$stockTableBody = $stockTable.find('tbody'),
rowTemplate = '<tr data-symbol="{Symbol}"><td>{Symbol}</td><td>{Price}</td><td>{DayOpen}</td><td>{Direction} {Change}</td><td>{PercentChange}</td></tr>';

function formatStock(stock) {
return $.extend(stock, {
Price: stock.Price.toFixed(2),
PercentChange: (stock.PercentChange * 100).toFixed(2) + '%',
Direction: stock.Change === 0 ? '' : stock.Change >= 0 ? up : down
});
}

function init() {
ticker.server.getAllStocks().done(function (stocks) {
$stockTableBody.empty();
$.each(stocks, function () {
var stock = formatStock(this);
$stockTableBody.append(rowTemplate.supplant(stock));
});
});
}

// Add a client-side hub method that the server will call
ticker.client.updateStockPrice = function (stock) {
var displayStock = formatStock(stock),
$row = $(rowTemplate.supplant(displayStock));

$stockTableBody.find('tr[data-symbol=' + stock.Symbol + ']')
.replaceWith($row);
}

// Start the connection
$.connection.hub.start().done(init);

});

result:





内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: