• SignalR学习笔记(三)Self-Host


    SignalR可以借助Owin摆脱对IIS的依赖,实现Self-Host,使得SignalR有了部署在非Windows平台的可能。

    什么是Owin

    Owin的英文全称是Open Web Interface for .NET, 他定义了Web应用程序和Web服务器之间的接口。他的作用就是解除了Web应用程序与Web服务器之间的耦合,从而使Web应用程序不再依赖于具体的Web服务器,已ASP.NET应用程序为例,以前需要依赖于IIS,  引入Owin之后,他只依赖与Owin提供的接口,所以所有实现Owin接口的Web服务器都可以替换掉IIS。

    如何在控制台程序中实现SignalR Self-Host

     

    创建一个空的控制台程序

    引入SignalR SelfHost包

    打开Package Manager Console面板,输入以下命令安装SignalR Self Host包。

    Install-package Microsoft.AspNet.SignalR.SelfHost

    其他可能需要引入的包

    因为如果使用Self-Host, 通常会指定一个独立的端口或者独立ip,这样就会出现跨域的问题,如果出现跨域问题,请引入Owin的CORS包

    Install-package Microsoft.Owin.Cors

    使用Owin启动一个Web服务器

        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                string url = "http://localhost:9021";
    
                using (WebApp.Start(url))
    
                {
    
                    Console.WriteLine("Server running on {0}", url);
    
                    Console.ReadKey();
    
                }
    
            }
    
    }

    添加Owin启动类

        class Startup
    
        {
    
            public void Configuration(IAppBuilder app)
    
            {
    
                //允许所有域名跨域访问
    
                app.UseCors(CorsOptions.AllowAll);
    
     
    
                //启动SignalR
    
                app.MapSignalR();
    
            }
    
        }


     

    添加Hub代码

    这里我们可以直接把学习笔记(一)中的Hub代码直接Copy过来,最终的的Self Host代码如下

    using Microsoft.AspNet.SignalR;
    
    using Microsoft.Owin.Cors;
    
    using Microsoft.Owin.Hosting;
    
    using Owin;
    
    using System;
    
    using System.Collections.Generic;
    
    using System.Linq;
    
     
    
    namespace SignalRSelfHost
    
    {
    
        class Program
    
        {
    
            static void Main(string[] args)
    
            {
    
                string url = "http://localhost:9021";
    
                using (WebApp.Start(url))
    
                {
    
                    Console.WriteLine("Server running on {0}", url);
    
                    Console.ReadKey();
    
                }
    
            }
    
        }
    
     
    
        class Startup
    
        {
    
            public void Configuration(IAppBuilder app)
    
            {
    
                //允许所有域名跨域访问
    
                app.UseCors(CorsOptions.AllowAll);
    
     
    
                //启动SignalR
    
                app.MapSignalR();
    
            }
    
        }
    
     
    
        public class ChatRoomHub : Hub
    
        {
    
            private static Dictionary<string, string> _nickNames = new Dictionary<string, string>();
    
     
    
            public void SetNickName(string nickName)
    
            {
    
                //当Hub启动完毕,每个连接到这个Hub的客户端都会自动分配一个唯一的ConnectionId。
    
                //当SignalR向指定客户端推送消息的时候,需要指定ConnectionId, 所以这里需要记录一下每个昵称对应的客户端ConnectionId
    
                _nickNames.Add(Context.ConnectionId, nickName);
    
     
    
                //当用户设置昵称之后,需要发送欢迎信息到所有的用户客户端,调用客户端receiveWelcomeMessage方法显示欢迎信息
    
                Clients.All.ReceiveWelcomeMessage($"{nickName}进入聊天室。");
    
            }
    
     
    
            public void Send(string nickName, string message)
    
            {
    
                if (string.IsNullOrWhiteSpace(nickName) || string.IsNullOrWhiteSpace(message))
    
                {
    
                    //如果用户昵称或者消息不存在,就不做任何操作
    
                    return;
    
                }
    
     
    
                if (message.StartsWith("to") && message.Split(' ').Length == 3)
    
                {
    
                    //私聊消息
    
                    var toUserName = message.Split(' ')[1];
    
     
    
                    if (_nickNames.ContainsValue(toUserName))
    
                    {
    
                        var connectionId = _nickNames.First(p => p.Value == toUserName).Key;
    
     
    
                        if (!string.IsNullOrWhiteSpace(connectionId) && connectionId != Context.ConnectionId)
    
                        {
    
                            Clients.Client(connectionId).ReceivePrivateMessage(nickName, message.Split(' ')[2]);
    
                        }
    
                    }
    
                }
    
                else
    
                {
    
                    //普通广播消息
    
                    if (_nickNames.ContainsValue(nickName))
    
                    {
    
                        Clients.All.ReceiveBroadcastMessage(nickName, message);
    
                    }
    
                }
    
            }
    
        }
    
    }


     

    运行程序

    按Ctrl+F5启动控制台程序, 显示Server running on xxxxx.表明服务器启动成功。

     

    添加聊天室网页

    这里需要重新创建一个空的Web程序

    添加所需SignalR库

    因为SignalR服务器已经移到了控制台程序当中,所以这里不需要应用Microsft.AspNet.SignalR库了

    这里仅需要引入SignalR的客户端脚本

    Install-package Microsoft.AspNet.SignalR.JS

    添加聊天网页

    这里我们将学习笔记(一)的代码直接copy过来,稍作修改。

    1. 原先我们引用<script src="signalr/hubs"></script>需要替换为<script src="http://localhost:9021/signalr/hubs"></script>
    2. 在创建Hub代理之前,需要设置SignalR服务器的地址

    $.connection.hub.url = 'http://localhost:9021/signalr';

    最终网页代码

    <!DOCTYPE html>
    
    <html>
    
    <head>
    
        <title>SignalR Simple Chat</title>
    
        <style type="text/css">
    
            .container {
    
                background-color: #99CCFF;
    
                border: thick solid #808080;
    
                padding: 20px;
    
                margin: 20px;
    
            }
    
        </style>
    
    </head>
    
    <body>
    
        <div class="container">
    
            <input type="text" id="message" />
    
            <input type="button" id="sendmessage" value="Send" />
    
            <input type="hidden" id="displayname" />
    
            <ul id="discussion"></ul>
    
        </div>
    
        <script src="Scripts/jquery-1.6.4.min.js"></script>
    
        <script src="Scripts/jquery.signalR-2.2.2.min.js"></script>
    
        <!--<script src="signalr/hubs"></script>-->
    
        <script src="http://localhost:9021/signalr/hubs"></script>
    
     
    
        <script type="text/javascript">
    
            $(function () {
    
     
    
                $.connection.hub.url = 'http://localhost:9021/signalr';
    
     
    
                //使用代理模式, 创建客户端的hub代理
    
                var chat = $.connection.chatRoomHub;
    
     
    
                //服务器Hub中, 调用ReceiveWelcomeMessage方法时, 会执行客户端的chat.client.receiveBroadcastMessage方法
    
                chat.client.receiveBroadcastMessage = function (name, message) {
    
     
    
                    //防JS输入
    
                    var encodedName = $('<div />').text(name).html();
    
                    var encodedMsg = $('<div />').text(message).html();
    
     
    
                    $('#discussion').append('<li><strong>' + encodedName
    
                        + '</strong>:  ' + encodedMsg + '</li>');
    
                };
    
     
    
                //服务器Hub中, 调用ReceiveWelcomeMessage方法时, 会执行客户端的chat.client.receiveWelcomeMessage方法
    
                chat.client.receiveWelcomeMessage = function (message) {
    
                    var encodedMsg = $('<div />').text(message).html();
    
     
    
                    $('#discussion').append('<li><strong style="color:blue">' + encodedMsg
    
                        + '</strong></li>');
    
                };
    
     
    
                //服务器Hub中, 调用ReceivePrivateMessage方法时, 会执行客户端的chat.client.receivePrivateMessage方法
    
                chat.client.receivePrivateMessage = function (name, message) {
    
                    var encodedName = $('<div />').text(name).html();
    
                    var encodedMsg = $('<div />').text(message).html();
    
     
    
                    $('#discussion').append('<li><strong style="color: green">' + encodedName
    
                        + '偷偷的跟你说</strong>:  ' + encodedMsg + '</li>');
    
                };
    
     
    
                //通过代理连接到服务器Hub
    
                $.connection.hub.start().done(function () {
    
                    $('#sendmessage').click(function () {
    
                        chat.server.send($('#displayname').val(), $('#message').val());
    
     
    
                        $('#message').val('').focus();
    
                    });
    
     
    
                    //连接成功后, 需要用户立刻输入昵称
    
                    $('#displayname').val(prompt('Enter your name:', ''));
    
                    chat.server.setNickName($('#displayname').val());
    
                    $('#message').focus();
    
                });
    
            });
    
        </script>
    
    </body>
    
    </html>


     

    启动程序,效果如下

    酷炫功能

    使用Self-Host之后,我们可以实现一个很酷炫的功能,在控制台程序中监控用户的输入

    public class ChatRoomHub : Hub
    
        {
    
            private static Dictionary<string, string> _nickNames = new Dictionary<string, string>();
    
     
    
            public void SetNickName(string nickName)
    
            {
    
                //当Hub启动完毕,每个连接到这个Hub的客户端都会自动分配一个唯一的ConnectionId。
    
                //当SignalR向指定客户端推送消息的时候,需要指定ConnectionId, 所以这里需要记录一下每个昵称对应的客户端ConnectionId
    
                _nickNames.Add(Context.ConnectionId, nickName);
    
     
    
                //当用户设置昵称之后,需要发送欢迎信息到所有的用户客户端,调用客户端receiveWelcomeMessage方法显示欢迎信息
    
                Clients.All.ReceiveWelcomeMessage($"{nickName}进入聊天室。");
    
                Console.WriteLine($"{nickName}进入聊天室。");
    
            }
    
     
    
            public void Send(string nickName, string message)
    
            {
    
                if (string.IsNullOrWhiteSpace(nickName) || string.IsNullOrWhiteSpace(message))
    
                {
    
                    //如果用户昵称或者消息不存在,就不做任何操作
    
                    return;
    
                }
    
     
    
                if (message.StartsWith("to") && message.Split(' ').Length == 3)
    
                {
    
                    //私聊消息
    
                    var toUserName = message.Split(' ')[1];
    
     
    
                    if (_nickNames.ContainsValue(toUserName))
    
                    {
    
                        var connectionId = _nickNames.First(p => p.Value == toUserName).Key;
    
     
    
                        if (!string.IsNullOrWhiteSpace(connectionId) && connectionId != Context.ConnectionId)
    
                        {
    
                            Clients.Client(connectionId).ReceivePrivateMessage(nickName, message.Split(' ')[2]);
    
                            Console.WriteLine($"{nickName}偷偷对{toUserName}说:{message}");
    
                        }
    
                    }
    
                }
    
                else
    
                {
    
                    //普通广播消息
    
                    if (_nickNames.ContainsValue(nickName))
    
                    {
    
                        Clients.All.ReceiveBroadcastMessage(nickName, message);
    
                        Console.WriteLine($"{nickName}对大家说:{message}");
    
                    }
    
                }
    
            }
    
        }


     

  • 相关阅读:
    20145201 《Java程序设计》第四周学习总结
    20145201 《Java程序设计》第三周学习总结
    20145201 《Java程序设计》第二周学习总结
    20145201 《Java程序设计》第一周学习总结(修改)
    输入与输出
    Fibonacci
    Collection与Map
    异常处理
    接口和多态
    继承与多态
  • 原文地址:https://www.cnblogs.com/lwqlun/p/9095089.html
Copyright © 2020-2023  润新知