一、前言

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

SignalR控制台自托管服务端向web客户端指定用户推送数据,客户端断线重连的更多相关文章

  1. 使用SignalR ASP.NET Core来简单实现一个后台实时推送数据给Echarts展示图表的功能

    什么是 SignalR ASP.NET Core ASP.NET Core SignalR 是一种开放源代码库,可简化将实时 web 功能添加到应用程序的功能. 实时 web 功能使服务器端代码可以立 ...

  2. SignalR指定用户推送消息

    一.首先,在MVC项目中安装SingalR包(SingalR2.0需要.net4.5以上,VS2010可以安装1.1.3版本,本例为VS2010+SignalR1.1.3). 打开工具-NuGet程序 ...

  3. SuperSocket主动从服务器端推送数据到客户端

    关键字: 主动推送, 推送数据, 客户端推送, 获取Session, 发送数据, 回话快照 通过Session对象发送数据到客户端   前面已经说过,AppSession 代表了一个逻辑的 socke ...

  4. Asp.net Core3.1+Vue 使用SignalR推送数据

    本文就简单使用 往前端页面推送消息 SignalR 是什么 SignalR是一个.NET Core/.NET Framework的开源实时框架. SignalR的可使用Web Socket, Serv ...

  5. 使用Pushlet将消息从服务器端推送到客户端

    使用Pushlet来实现服务器端向客户端推送信息 1.   实现方式: 有两种实现方式: 1.         通过配置文件来实现定时的从服务器端向客户端推送信息 2.         通过API主动 ...

  6. ASP.NET SignalR 系列(四)之指定对象推送

    在上一章讲到了广播推送,即所有订阅的用户都能收到,这种适合于信息广播. 接下来介绍如何给指定的对象推送 在讲这个之前先说明一下连接创建的基础知识 1.每个页面与服务端创建连接并启动时,这时服务端会产生 ...

  7. 利用Ajax+MSMQ(消息队列)+WebService实现服务器端向客户端的信息推送

    需求: 每当数据库有数据更新时,推送到客户端 软需求: 1.服务器资源有限,要求资源占用尽可能小: 2.项目可控,不许调用第三方不可信不稳定的方法. 已有事例: 1.58到家采用的方法是TCP的长连接 ...

  8. C#服务端通过Socket推送数据到Android端App中

    需求: 描述:实时在客户端上获取到哪些款需要补货. 要求: 后台需要使用c#,并且哪些需要补货的逻辑写在公司框架内,客户端采用PDA(即Android客户端 版本4.4) . 用户打开了补货通知页面时 ...

  9. DP使用GUI推送WIN客户端是报110:1022错误的解决办法

    在使用GUI推送WIN客户端时,输入用户名和密码后报错: [Critical 110::1022]  Cannot connect to the SCM (Service Control Manage ...

随机推荐

  1. 使用gitlab ci构建IOS包并发送通知消息到企业微信

    在之前的文章中,我们介绍了使用gitlab ci构建Android包的方法.今天我们介绍使用gitlab ci如何构建IOS包,并且在打包成功或者失败时,如何将消息通知到企业微信. 如果对gitlab ...

  2. GraphQL-- 使用Apollo Server搭建Node服务端

    一.关于Apollo Server Apollo Server是一种使用JS创建GraphQL服务端的一个方案.它的兼容性比较好,可以很好地和GraphQL客户端进行兼容.同时它可以 独立作为服务端进 ...

  3. 「雕爷学编程」Arduino动手做(24)——水位传感器模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  4. spark机器学习从0到1基本的统计工具之(三)

      给定一个数据集,数据分析师一般会先观察一下数据集的基本情况,称之为汇总统计或者概要性统计.一般的概要性统计用于概括一系列观测值,包括位置或集中趋势(比如算术平均值.中位数.众数和四分位均值),展型 ...

  5. pyhton中的深浅copy

    深浅拷贝:数据分离情况 1. =赋值:数据完全共享(指向内存中的同一个对象)被赋值的变量指向的数据和原变量的数据都是指向内存中的同一个地址: (1)如果是不可变数据类型(数字.字符串等),修改其中的一 ...

  6. package.json中^,~的区别

    https://blog.csdn.net/peaceoncemore/article/details/79195206 "devDependencies": {    " ...

  7. 洛谷P2468 粟粟的书架

    题目链接:https://www.luogu.org/problemnew/show/P2468 知识点: 可持久化线段树.二分.前缀和 解题思路: 对于 \(R, C \le 200, M \le ...

  8. CF894B Ralph And His Magic Field

    题目链接:http://codeforces.com/contest/894/problem/B 题目大意: 往一个 \(n \times m\) 的网格中填数字 \((1 \le n,m \le 1 ...

  9. WordPress 安全配置

    关闭后台主题编辑功能 WordPress后台的主题一旦权限开放就可以在后台直接编辑,如果没有开放则只可浏览.主机若有安装suPHP默认就是可以编辑.如果你觉得这项功能用不到,建议您可以关闭它,毕竟直接 ...

  10. MyBatis的使用增删改查(两种分页查询)

    文件目录 写一下每个文件的代码  UserDao.java package cn.zys.dao; import java.io.IOException; import java.util.List; ...