建立一個 SignalR 連接 配置 SignalR 連接 在 WPF 客戶端里設置連接的最大值 設置 Query String 參數 讀取 query string 指定傳輸協議 可以指定以下四種方式 LongPollingTransport ServerSentEventsTransport W ...
建立一個 SignalR 連接
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await hubConnection.Start();
配置 SignalR 連接
在 WPF 客戶端里設置連接的最大值
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); ServicePointManager.DefaultConnectionLimit = 10; await hubConnection.Start();
設置 Query String 參數
var querystringData = new Dictionary<string, string>(); querystringData.Add("contosochatversion", "1.0"); var connection = new HubConnection("http://contoso.com/", querystringData);
讀取 query string
public class StockTickerHub : Hub { public override Task OnConnected() { var version = Context.QueryString["contosochatversion"]; if (version != "1.0") { Clients.Caller.notifyWrongVersion(); } return base.OnConnected(); } }
指定傳輸協議
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await hubConnection.Start(new LongPollingTransport());
可以指定以下四種方式
- LongPollingTransport
- ServerSentEventsTransport
- WebSocketTransport (只有在 server and client 都使用 .NET 4.5的情況下才能使用)
- AutoTransport(自動選擇)
指定 Http Header
hubConnection = new hubConnection("http://www.contoso.com/"); connection.Headers.Add("headername", "headervalue"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await connection.Start();
指定 Client 證書
hubConnection = new hubConnection("http://www.contoso.com/"); hubConnection.AddClientCertificate(X509Certificate.CreateFromCertFile("MyCert.cer")); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await connection.Start();
創建 Hub proxy
服務端
public class StockTickerHub : Hub
客戶端
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await hubConnection.Start();
如果你的 Hub 類使用了 HubName 特性,那麼就需要使用 HubName 的值來調用。
服務端
[HubName("stockTicker")] public class StockTickerHub : Hub
客戶端
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("stockTicker"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await hubConnection.Start();
如果使用 HubName 多次調用 HubConnection.CreateHubProxy,那麼會得到緩存的相同的 IHubProxy 對象。
如何定義在 Server 端調用的 Client 方法
無參方法
Server 端
public class StockTickerHub : Hub { public void NotifyAllClients() { Clients.All.Notify(); } }
客戶端
var hubConnection = new HubConnection("http://www.contoso.com/"); IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHub.On("notify", () => // Context is a reference to SynchronizationContext.Current Context.Post(delegate { textBox.Text += "Notified!\n"; }, null) ); await hubConnection.Start();
有參指定參數類型
Sever 端
public void BroadcastStockPrice(Stock stock) { context.Clients.Others.UpdateStockPrice(stock); }
用作參數的 Stock 類
public class Stock
{
public string Symbol { get; set; }
public decimal Price { get; set; }
}
客戶端代碼
stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => // Context is a reference to SynchronizationContext.Current Context.Post(delegate { textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price); }, null) );
有參,指定動態類型
server 端
public void BroadcastStockPrice(Stock stock) { context.Clients.Others.UpdateStockPrice(stock); }
用作參數的 Stock 類
public class Stock { public string Symbol { get; set; } public decimal Price { get; set; } }
客戶端代碼
stockTickerHubProxy.On("UpdateStockPrice", stock => // Context is a reference to SynchronizationContext.Current Context.Post(delegate { textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price); }, null) );
移除Handler
var updateStockPriceHandler = stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Context.Post(delegate { textBox.Text += string.Format("Stock update for {0} new price {1}\n", stock.Symbol, stock.Price); }, null) ); updateStockPriceHandler.Dispose();
從客戶端調用服務端方法
使用 HubProxy 的 Invoke 方法來調用服務端的方法。
服務端方法沒有返回值
public class StockTickerHub : Hub { public void JoinGroup(string groupName) { Groups.Add(Context.ConnectionId, groupName); } }
客戶端調用伺服器沒有返回值的方法
stockTickerHubProxy.Invoke("JoinGroup", "SignalRChatRoom");
服務端方法有返回值,並且有一個複雜類型的參數
public IEnumerable<Stock> AddStock(Stock stock) { _stockTicker.AddStock(stock); return _stockTicker.GetAllStocks(); }
Stock 類
public class Stock { public string Symbol { get; set; } public decimal Price { get; set; } }
客戶端調用有返回值和複雜類型參數的方法,.Net 4.5 里使用非同步方法
var stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("AddStock", new Stock() { Symbol = "MSFT" }); foreach (Stock stock in stocks) { textBox.Text += string.Format("Symbol: {0} price: {1}\n", stock.Symbol, stock.Price); }
如何處理連接的生命周期事件
SignalR 提供了下述你可以捕獲的生命周期事件。
- received: 當任何數據通過連接獲取到的時候執行。可以得到數據。
- connectionSlow: 當客戶端檢測到緩慢或者不流暢的連接的時候執行。
- reconnecting: 當潛在的協議重新開始連接的時候執行。
- reconnected: 當潛在的協議以及重新建立連接的時候執行。
- stateChanged: 當連接的狀態發生改變的時候執行。可以提供一個舊的和新的狀態(Connecting, Connected, Reconnecting, 或者 Disconnected)。
- Closed: 當連接中斷以後執行。
hubConnection.ConnectionSlow += () => Console.WriteLine("Connection problems.");
捕獲異常
如果你不在服務端明確地打開詳細錯誤信息,那麼SignalR只會列出一些簡單的錯誤信息,你可以通過下麵的代碼開啟詳細錯誤信息記錄。
var hubConfiguration = new HubConfiguration(); hubConfiguration.EnableDetailedErrors = true; App.MapSignalR(hubConfiguration);
給 connection 對象添加一個 error 處理事件。
hubConnection.Error += ex => Console.WriteLine("SignalR error: {0}", ex.Message);
用 try - catch 捕獲異常
try { IEnumerable<Stock> stocks = await stockTickerHub.Invoke<IEnumerable<Stock>>("GetAllStocks"); foreach (Stock stock in stocks) { Console.WriteLine("Symbol: {0} price: {1}", stock.Symbol, stock.Price); } } catch (Exception ex) { Console.WriteLine("Error invoking GetAllStocks: {0}", ex.Message); }
開啟客戶端日誌
var hubConnection = new HubConnection("http://www.contoso.com/"); hubConnection.TraceLevel = TraceLevels.All; hubConnection.TraceWriter = Console.Out; IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("StockTickerHub"); stockTickerHubProxy.On<Stock>("UpdateStockPrice", stock => Console.WriteLine("Stock update for {0} new price {1}", stock.Symbol, stock.Price)); await hubConnection.Start();
參考鏈接:
https://docs.microsoft.com/zh-cn/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-net-client