SIgnalR是微软开发的一套通信组件,如果听说过websocket的话,那么SignalR功能和websocket类似,提供客户端和服务端的实时通信。
SignalR客户端可用于.net平台和js上,服务端(afaik)是在.net上的。
对于js和服务器间的通信,signalR相较于websocket的主要好处在于兼容性,websocket是H5的特性,对于老式浏览器不支持,SignalR会自动退回长连接等方式,保证跨浏览器支持。
简单记录一下SignalR的客户端和服务端,都以c#为例。
服务端
准备工作
引入SignalR的程序包,可在NuGet中找到
配置初始化
这里使用的是官网上给出的通过Owin来配置的方式。
需要创造一个StartUp类,对SignalR进行注册。
[assembly: OwinStartup(typeof(RS2_Test_Hub.Startup))]
namespace RS2_Test_Hub
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration();
//这里第一个参数是提供SignalR的路径,默认是/signalR,这里我改为了根路径
app.MapSignalR("", hubConfiguration);
}
}
}
提供SignalR服务
SignalR显然需要网路来连接,所以需要一个Web服务去承载他。
一开始我在测试的时候,配置好了SignalR服务端,但客户端怎么也连不上。 检查以后,发现仅仅配置注册,本机并没有开端口监听 后来搜索半天,才明白需要额外的web服务作为载体才能提供出来。 其实我在配置的时候,也好奇哪里有配置端口的地方。。 用这种高级封装的语言,有时候会很方便,但是过多的细节封装,使人对他的实现原理了解更加困难,碰到问题时,更加难以解决 |
如果不是通过IIS等方式,可以使用SelfHost方式,启动一个C#的HttpServer来提供服务 。
这需要引入Owin的SelfHost,并在程序启动时,同时开启这个简单的Web服务
string url = "http://127.0.0.1:5570";//这里以本机测试,5570端口为例
WebApp.Start(url);
真正实现业务的服务类
服务类,这里叫做Hub,需要继承自Hub类
[HubName("SignalR_Hub_Inventory")]
public class MyHub : Hub
{
public void NewContosoChatMessage(string name, string message)
{
Clients.All.addNewMessageToPage(name, message);
}
public IEnumerable<Stock> GetAllStocks()
{
return _stockTicker.GetAllStocks();
}
}</code></pre>
- Hub的类名叫做MyHub,但是指定了HubName属性
- 如果未指定,客户端需要用`myHub`名称来连接
- 这里指定了,所以需要用特定的名称来连接
- 这里定义了两个public方法,这两个可被客户端调用
- 第一个方法,又调用了客户端的方法
- 第二个方法,可以无视Stock类,这是我示例的类,这里展示的是,可以返回列表类型
客户端
配置和初始化
引入SignalR包就不必说了,初始化相关:
var hubConnection = new HubConnection("http://localhost:5700/");
IHubProxy stockTickerHubProxy = hubConnection.CreateHubProxy("SignalR_Hub_Inventory");
stockTickerHubProxy.On<Msg>("addNewMessageToPage", msg => Console.WriteLine("Name {0} Message {1}", msg.name, msg.message));
await hubConnection.Start();
- 创建连接,指定连接的服务端Hub地址
- 指定要连接的Hub,这里连接的是上面创建的`SignalR_Hub_Inventory`
- On方法,定义了客户端可以相应的服务端的请求
- 最后调用Start,开始连接
调用服务端方法
在创建的hub上,通过名字指定需要调用的服务端方法即可
var stock = _hub.Invoke<IList<Stock>>("GetAllStocks", null);
- 第二个null参数,实际是服务端需要的参数列表
断线重连
SignalR客户端在连接断开后,会自动尝试重连,但是经过一段时间如果仍然没有连上(似乎是110秒),则会断开了,如果我们想让客户端始终尝试重连,可以通过捕捉断开事件,手动触发连接。
Hub连接创建时,注册断开事件:
_hubConnection.Closed += HandleClosed;
在处理事件中重新连接:
private void HandleClosed()
{
_hubConnection.Start().Wait(_connectionTimeout);
}
当然,实际处理中,断开后可以通过定时器,过一段时间再去重连,毕竟刚刚断开也是因为没有连上的原因。
结语
SignalR设计的功能还有很多,例如分组,配置等等。
暂时用到的就是这些