建立一个 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查询第一篇

    第一个小知识点: clear 在oracle中也可以用以清除屏幕上的内容 第二个小知识点: 在一个表中插入自身的查询结果 insert into my_table (id,name,age) sele ...

  2. python通过excel对数据库插入数据

    1.需要有两个包文件xlrd及MySQLdb(其他数据库可以另外找) 2.读取excel文件信息 book = xlrd.open_workbook(文件地址) 3.建立MySQL链接 databas ...

  3. Here文档

    Here文档为需要输入的程序,例如,mail.sort和cat等接收在线文本,直到遇到用户定义的结束符号为止.最常用的用户是在Shell脚本中和case命令一起创建菜单.自动登录等等. 1.建立菜单 ...

  4. post和get方式区别

    Ajax中我们经常用到get和post请求.那么什么时候用get请求,什么时候用post方式请求呢? 在做回答前我们首先要了解get和post的区别.1. get是把参数数据队列加到提交表单的ACTI ...

  5. Java IO学习笔记五

    管道流 管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream).管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入 ...

  6. 2~62位任意进制转换(c++)

    进制转换的符号表为[0-9a-zA-Z],共61个字符,最大可表示62进制. 思路是原进制先转换为10进制,再转换到目标进制. 疑问: 对于负数,有小伙伴说可以直接将符号丢弃,按照整数进行进位转换,最 ...

  7. java实现Excel的导入、导出

    一.Excel的导入 导入可采用两种方式,一种是JXL,另一种是POI,但前者不能读取高版本的Excel(07以上),后者更具兼容性.由于对两种方式都进行了尝试,就都贴出来分享(若有错误,请给予指正) ...

  8. 跨域访问之JSONP

    跨域 在平常的工作中常常会遇到A站点的需要访问B站点的资源. 这时就产生了跨域访问. 跨域是指从一个域名的网页去请求另一个域名的资源.浏览器遵循同源策略,不允许A站点的Javascript 读取B站点 ...

  9. 常用PHP函数的封装

    PHP获取文件扩展名(后缀) function getExtension($filename){ $myext = substr($filename, strrpos($filename, '.')) ...

  10. bootstrap table 插件多语言切换

    在bootstrap中的bootstrap table 插件在多语言切换的审核,只需要如下操作 引入bootstrap-table-locale-all.js文件 $('#Grid').bootstr ...