一、前言

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. 让.NetCore程序跑在任何有docker的地方

    一.分别在Windows/Mac/Centos上安装Docker Windows上下载地址:https://docs.docker.com/docker-for-windows/install/(wi ...

  2. Redux:pre

    If you aren't familiar with state management libraries like Redux or MobX, don't use context. For ma ...

  3. Oracle 大数据查询优化方法

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  4. vue-cli搭建vue项目

    1 安装node,npm  npm i node npmnode -v npm -v 2 查看webpack版本,这里要注意,webpack如果为4.0,可能不兼容vue-cli 先卸载 npm un ...

  5. 2.3 Go内置函数

    内置函数 Go 语言拥有一些不需要进行导入操作就可以使用的内置函数.它们有时可以针对不同的类型进行操作,例如:len.cap 和 append,或必须用于系统级的操作,例如:panic.因此,它们需要 ...

  6. 自定义docker的镜像

  7. vue项目中使用bpmn-流程图json属性转xml(七篇更新完成)

    内容概述 本系列“vue项目中使用bpmn-xxxx”分为七篇,均为自己使用过程中用到的实例,手工原创,目前陆续更新中.主要包括vue项目中bpmn使用实例.应用技巧.基本知识点总结和需要注意事项,具 ...

  8. DPDK Mempool 库原理(学习笔记)

    1 前置知识点学习(了解) 从CPU到实际的存储节点,依据层级划分:Channel > DIMM > Rank > Chip > Bank > Row /Column 1 ...

  9. 04.PageNumberPagination分页

    一.使用默认分页 1.settings 设置 REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.Pag ...

  10. 【MySQL】大白话讲讲主从架构的几种搭配方式详解

    话不多,直接上图: 主要来详细讲讲各个搭配 1>一主一从(成本最低): 并不是用来提高程序性能的,主要是用来做数据的热备(即如果master节点挂掉的话,slave节点能充当master节点), ...