SignalR控制台自托管服务端向web客户端指定用户推送数据,客户端断线重连
一、前言
SignalR是微软推出的开源实时通信框架。其内部使用Web Socket, Server Sent Events 和 Long Polling作为底层传输方式,SignalR会根据客户端和服务端的支持情况,采用回落机制来选择一种传输方式,Web Socket是首选的。在web开发中,SignalR可以很好的解决传统ajax轮询的问题,真正做到实时通信。
二、编码
- 首先创建2个项目,一个控制台项目,一个web项目。控制台项目作为SignalR服务端,web项目作为客户端。
- 先从服务端开始:
安装NuGet包
控制台程序作为宿主实现自托管,需要安装:Microsoft.AspNet.SignalR.SelfHost
添加跨域支持:Microsoft.Owin.Cors
- 服务端SignalRServer.Program代码:
using Microsoft.AspNet.SignalR;
using Microsoft.Owin.Cors;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
namespace SignalRServer
{
class Program
{
static void Main(string[] args)
{
var url = "http://localhost:8019";
using (WebApp.Start(url))
{
Console.WriteLine("SignalR运行:" + url);
Console.WriteLine("输入要发送的消息,用户与消息之间用空格隔开:");
var hub = GlobalHost.ConnectionManager.GetHubContext<CustomHub>();
while (true)
{
var str = Console.ReadLine();
hub.Clients.Client(CustomHub.OnLineUsers[str.Split(' ')[0]]).refreshData(str.Split(' ')[1]);
}
}
}
}
public class CustomHub : Hub
{
//在线用户
public static ConcurrentDictionary<string, string> OnLineUsers = new ConcurrentDictionary<string, string>();
public override Task OnConnected()
{
string clientName = Context.QueryString["clientName"].ToString();
OnLineUsers.AddOrUpdate(clientName, Context.ConnectionId, (key, value) =>
{
return Context.ConnectionId;
});
Console.WriteLine($"{clientName}:{Context.ConnectionId}已连接。");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopCalled)
{
string clientName = Context.QueryString["clientName"].ToString();
string client;
OnLineUsers.TryRemove(clientName, out client);
Console.WriteLine($"{clientName}:{Context.ConnectionId}已断开。");
return base.OnDisconnected(stopCalled);
}
public override Task OnReconnected()
{
string clientName = Context.QueryString["clientName"].ToString();
OnLineUsers.AddOrUpdate(clientName, Context.ConnectionId, (key, value) =>
{
return Context.ConnectionId;
});
Console.WriteLine($"{clientName}:{Context.ConnectionId}已重连。");
return base.OnReconnected();
}
}
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll);
app.MapSignalR();
}
}
}
以上代码大致就是指定一个url启动SignalR服务,CustomHub中维护了一个在线客户端集合,控制台根据输入的信息发送到对应的客户端...
- 下面是客户端
同样先安装NuGet包
安装Microsoft.AspNet.SignalR.JS
- 创建2个视图User1,User2,用来代表2个不同用户
User1.cshtml代码,支持断线重连:
@{
ViewBag.Title = "Index";
Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script id="signalr_script" src="http://localhost:8019/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
//连接Signalr服务器
signalrInit();
});
//signalr初始化配置
function signalrInit() {
try {
//Set the hubs URL for the connection
$.connection.hub.url = 'http://localhost:8019/signalr';
$.connection.hub.qs = { "clientName": "user1" };
// Declare a proxy to reference the hub.
var chat = $.connection.customHub;
// Create a function that the hub can call to broadcast messages.
chat.client.refreshData = function (message) {
//TODO:收到服务端数据
appendMessage(message);
};
signalrConnection();
$.connection.hub.disconnected(function () {
appendMessage('SignalR连接断开!');
//重连
setTimeout(signalrConnection, 10000);
});
//$.connection.hub.stateChanged(function (change) { console.log(change); });
} catch (e) {
appendMessage("SignalR连接异常" + e);
//重新加载hubs
$.getScript('http://localhost:8019/signalr/hubs');
//重新初始化 断线重连
setTimeout(signalrInit, 10000);
}
}
//signalr连接
function signalrConnection() {
$.connection.hub.start()
.done(function () { appendMessage('SignalR建立连接成功'); })
.fail(function () { appendMessage('SignalR建立连接失败'); });
}
function appendMessage(message) {
$("#box").append("<p>" + message + "</p>");
}
</script>
<h1>User1</h1>
<div id="box">
</div>
User2.cshtml代码:
@{
ViewBag.Title = "Index";
Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script id="signalr_script" src="http://localhost:8019/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
//连接Signalr服务器
signalrInit();
});
//signalr初始化配置
function signalrInit() {
try {
//Set the hubs URL for the connection
$.connection.hub.url = 'http://localhost:8019/signalr';
$.connection.hub.qs = { "clientName": "user2" };
// Declare a proxy to reference the hub.
var chat = $.connection.customHub;
// Create a function that the hub can call to broadcast messages.
chat.client.refreshData = function (message) {
//TODO:收到服务端数据
appendMessage(message);
};
signalrConnection();
$.connection.hub.disconnected(function () {
appendMessage('SignalR连接断开!');
//重连
setTimeout(signalrConnection, 10000);
});
//$.connection.hub.stateChanged(function (change) { console.log(change); });
} catch (e) {
appendMessage("SignalR连接异常" + e);
//重新加载hubs
$.getScript('http://localhost:8019/signalr/hubs');
//重新初始化 断线重连
setTimeout(signalrInit, 10000);
}
}
//signalr连接
function signalrConnection() {
$.connection.hub.start()
.done(function () { appendMessage('SignalR建立连接成功'); })
.fail(function () { appendMessage('SignalR建立连接失败'); });
}
function appendMessage(message) {
$("#box").append("<p>" + message + "</p>");
}
</script>
<h1>User2</h1>
<div id="box">
</div>
三、效果
- 服务端和客户端的代码已完成,现在先运行一下服务端控制台程序。右键编译好的SignalRServer.exe,以管理员身份运行(最好是管理员身份运行,不然可能会报错)。
- 运行客户端,浏览器分别打开User1,User2页面
客户端已经显示连接成功
服务端也显示2个已连接 - 向User1发送消息:
- 向User2发送消息:
四、总结
以上就是SignalR的基本使用。
有一些可能的坑:
1.服务端控制台启动报错:尝试用管理员身份启动
2.服务端启动正常,客户端却无法连接,报错Cannot read property 'client' of undefined:有时候可能是端口的问题,换一个端口试一下
3.程序放到服务器,通过外网IP无法连接:WebApp.Start()尝试使用*号格式:http://*:8019
——本文使用【Typora】+【EasyBlogImageForTypora】编辑
欢迎关注我的公众号,一起学习。
如果本文对您有所帮助,您可以点击右下方的【推荐】按钮支持一下;文中如有不妥之处,还望指正,非常感谢!!!
作者:xhznl
出处:http://www.cnblogs.com/xhznl/
文章可以转载,但请注明出处