加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

SignalR控制台自托管服务端向web客户端指定用户推送数据,客户端

发布时间:2020-12-16 08:50:08 所属栏目:asp.Net 来源:网络整理
导读:一、前言 SignalR是微软推出的开源实时通信框架。其内部使用Web Socket,Server Sent Events 和 Long Polling作为底层传输方式,SignalR会根据客户端和服务端的支持情况,采用回落机制来选择一种传输方式,Web Socket是首选的。在web开发中,SignalR可以很好

一、前言

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,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);
        }
    }

    //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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读