建立一个 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 = ;
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

【SignalR学习系列】8. SignalR Hubs Api 详解(.Net C# 客户端)的更多相关文章

  1. 【SignalR学习系列】7. SignalR Hubs Api 详解(JavaScript 客户端)

    SignalR 的 generated proxy 服务端 public class ContosoChatHub : Hub { public void NewContosoChatMessage( ...

  2. prometheus学习系列十一: Prometheus exporter详解

    exporter详解 前面的系列中,我们在主机上面安装了node_exporter程序,该程序对外暴露一个用于获取当前监控样本数据的http的访问地址, 这个的一个程序成为exporter,Expor ...

  3. 【SignalR学习系列】6. SignalR Hubs Api 详解(C# Server 端)

    如何注册 SignalR 中间件 为了让客户端能够连接到 Hub ,当程序启动的时候你需要调用 MapSignalR 方法. 下面代码显示了如何在 OWIN startup 类里面定义 SignalR ...

  4. 【HANA系列】SAP HANA XS的JavaScript API详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA XS的Java ...

  5. 【HANA系列】【第五篇】SAP HANA XS的JavaScript API详解

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列][第五篇]SAP HANA XS ...

  6. hibernate学习(2)——api详解对象

    1   Configuration 配置对象 /详解Configuration对象 public class Configuration_test { @Test //Configuration 用户 ...

  7. Java8学习笔记(五)--Stream API详解[转]

    为什么需要 Stream Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 ...

  8. Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)

    一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...

  9. 大数据学习笔记——Spark工作机制以及API详解

    Spark工作机制以及API详解 本篇文章将会承接上篇关于如何部署Spark分布式集群的博客,会先对RDD编程中常见的API进行一个整理,接着再结合源代码以及注释详细地解读spark的作业提交流程,调 ...

随机推荐

  1. oracle日志挖掘

    oracle日志挖掘是一种十分强大的数据恢复技术,只要你保障你的归档日志和重做日志是完整的,那么就可以将你的数据恢复到任何时刻.简单叙述一下日志挖掘的基本原理,然后进行一个简单的小实验. 日志挖掘时基 ...

  2. integer与int区别以及integer.values()方法详解

    声明:本文为博主转载文章,原文地址见文末. 知识点1:integer和int的区别 /* * int是java提供的8种原始数据类型之一.Java为每个原始类型提供了封装类,Integer是java为 ...

  3. 解决Ubuntu开关机动画不正常方法

    联想的笔记本,显卡NVIDIA GT218M,默认使用开源的驱动,但挂起后,再唤醒就黑屏回不到桌面. 1.解决办法:安装NVIDIA专有驱动 $sudo apt-get install nvidia- ...

  4. JavaScript事件与例子

    事件,就是预先设置好的一段代码,等到用户触发的时候执行. 一:常见的事件: 1.关于鼠标的事件 onclick 鼠标单击触发 ondblclick 鼠标双击触发 onmouseover 鼠标移上触发 ...

  5. Hibernate执行原生态sql语句

    @Override public Integer update(String id, String username){ String sql = "update Team_CheLiang ...

  6. 查看java线程cpu占用情况的脚本

    #!/bin/bash [ $# -ne ] && exit jstack $ >/tmp/jstack.log -o THREAD,tid,time|sort -k2nr| s ...

  7. Array和ArrayList的区别与联系

    博主今天去了一个java的实习面试,发现有好多java最基础的数据结构对于博主来说反而感到陌生,在面试官问一些常见的例如HashMap这样的数据结构,博主能回答的头头是道,但是在问到Array和Arr ...

  8. php文件的管理

    一.先做一下简单的查看文件功能,文件中的文件和文件夹都显示,但是双击文件夹可以显示下一级子目录,双击"返回上一级"就可以返回到上一级目录 (1)先将需要管理的文件遍历出来,可以加个 ...

  9. html5小游戏基础知识

    显示一个DIV和隐藏一个DIV 首先,我们要显示一个DIV和隐藏一个DIV需要使用css里面使用: .hide{ display:none;} .show{display:block;} 在需要显示或 ...

  10. 利用CSS3新特性实现完全兼容的自定义滚动条。

    背景:最近项目里面因为统一页面风格,用到了自定义滚动条,在完成之前的那个滚动条的时候,与网上各个滚动条插件实现的方法类似,相当于造了轮子,通过css3的 网上看到的滚动条插件多数是通过监听内容的滚动事 ...