• SignalR消息推送(03)


    目录:

    • SignalR概念
    • 基本使用
    • 对点聊天

    1.SignalR

    是微软为实现实时通信而开发的一个类库。可进行分布式实时通信,远程代理实现。

    1.1 两大内部对象

    • Persisten Connection

        用于客户端和服务器端的持久连接。

    • Hub(集线器)对象

        用于信息交互,将服务器端的数据推送(push)至客户端。

    原理:客端建立与服端的连接。客端调用服端的方法。服端通过客端发送的请求,响应数据,调用客端的方法将数据推送至客端。

    1.2 基本使用

    • 创建一个MVC应用程序。
    • 在MVC项目的Models文件夹中添加新项 SignalR Hub集线器类。
    在创建的Hub类中添加如下代码:
    
    //hub别名,方便前台调用
    [HubName("getMsg")]
    public class MyHub : Hub
    {
    public void Send(string title,string msg)
    {
    //调用客户端的sendMessage()方法
    Clients.All.sendMessage(title,msg);  //其中Clients.All是dynamic类型,sendMessaage()方法是视图中js定义的function。
    }
    }
    • 在项目中添加 OWIN StartUp 类。
    public class Startup
    {
    public void Configuration(IAppBuilder app)
    {
    //注册管道,使用默认的虚拟地址,根目录下的"/signalr",
    //当然你也可以自己定义
    app.MapSignalR();
    }
    }
    • 创建控制器和视图
    //创建MessageController,并创建两个用于显示视图的action。
    //控制器代码:
    ublic class MessageController : Controller
    {
    //发送消息
    public ActionResult SendMessage()
    {
    return View();
    }
    //接收消息
    public ActionResult ReceiveMessage()
    {
    return View();
    }
    }
    
    //发送消息视图代码:
    <h2>发送消息</h2>
    <div>
    标题:<input type="text" id="title" />
    </div><br />
    <div>
    内容:<textarea id="message" rows="4" cols="30"></textarea>
    </div>
    <br />
    <div>
    <input type="button" id="sendmessage" value="发送" />
    </div>
    
    <script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
    <!--引用自动生成的SignalR 集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到 -->
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
    $(function () {
    // 引用自动生成的集线器代理(此处使用别名getMsg)
    var chat = $.connection.getMsg;
    // 集成器连接开始
    $.connection.hub.start().done(function () {
    // 服务连接完成,给发送按钮注册单击事件
    $('#sendmessage').click(function () {
    // 调用服务器端集线器的Send方法
    chat.server.send($("#title").val(), $('#message').val());  //又调用了客户端,客户端的函数就是添加信息列,就实现了广播消息功能
    });
    });
    });
    </script>
    
    //接收消息视图代码:
    <h2>接收消息</h2>
    <div>
    <br />
    <div id="msgcontent"></div>
    </div>
    <script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
    $(function () {
    // 引用自动生成的集线器代理
    var chat = $.connection.getMsg;
    // 定义服务器端调用的客户端sendMessage来显示新消息
    chat.client.sendMessage = function (title, message) {
    // 向页面发送接收的消息
    var html = "<div>标题:" + title + "消息内容:" + message + "</div>";
    $("#msgcontent").after(html);
    };
    // 集成器连接开始
    $.connection.hub.start(); //与SignalR服务建立连接
    });
    </script>

    //<!--引用SignalR库. -->

    <!--引用SignalR库. -->

    <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>

    <!--引用自动生成的SignalR 集线器(Hub)脚本 -->

    <script src="~/signalr/hubs"></script>

    1.3 实现点对点聊天

    Clients对象的所有属性或方法,具体的定义如下:

    public interface IHubConnectionContext<T>
    {
    T All { get; } // 代表所有客户端
    T AllExcept(params string[] excludeConnectionIds); //除了参数中的所有客户端
    T Client(string connectionId); // 特定的客户端,实现端对端聊天的关键
    T Clients(IList<string> connectionIds); // 参数中的客户端
    T Group(string groupName, params string[] excludeConnectionIds); // 指定客户端组,可以实现群聊
    T Groups(IList<string> groupNames, params string[] excludeConnectionIds);
    T User(string userId); // 特定的用户
    T Users(IList<string> userIds); // 参数中的用户
    }
    属性

    SignalR会每一个客户端分配一个ConnnectionId

    实现思路:

    • 客户端登入的时候记录下客户端的ConnnectionId,并将用户加入到一个静态数组中,该数据为了记录所有在线用户。
    • 用户可以点击在线用户中的用户聊天,在发送消息的时候,需要将ConnectionId一并传入到服务端。
    • 服务端根据传入的消息内容和ConnectionId调用Clients.Client(connnection).sendMessage方法来进行转发到对应的客户端。
    [HubName("Chat")]
    public class ChatHub : Hub
    {
    // 静态属性,在线用户列表
    public static List<UserInfo> OnlineUsers = new List<UserInfo>();
    
    //登录
    public void Login(string userId,string userName)
    {
    //获取客户端的ConnectionId
    var connnectId = Context.ConnectionId;
    OnlineUsers.Add(new UserInfo
    {
    ConnectionId = connnectId,
    UserId = userId,
    UserName = userName
    });
    // 所有客户端同步在线用户
    Clients.All.loadUser(OnlineUsers);
    }
    
    /// <summary>
    /// 发送私聊
    /// </summary>
    /// <param name="toUserId">接收方用户连接ID</param>
    /// <param name="message">内容</param>
    public void SendPrivateMessage(string toUserId, string message)
    {
    var fromUserId = Context.ConnectionId;
    var toUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
    var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);
    if (toUser != null && fromUser != null)
    {
    // 调用指定用户的客户端方法
    Clients.Client(toUserId).receivePrivateMessage(fromUser.UserName, message);
    }
    else
    {
    //表示对方不在线
    Clients.Caller.absentSubscriber();
    }
    }
       
    /// <summary>
    /// 断线时调用
    /// </summary>
    /// <param name="stopCalled"></param>
    /// <returns></returns>
    public override Task OnDisconnected(bool stopCalled)
    {
    var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);
    
    // 判断用户是否存在,存在则删除
    if (user == null) return base.OnDisconnected(stopCalled);
    Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); //调用客户端用户离线通知
    // 删除用户
    OnlineUsers.Remove(user);
    return base.OnDisconnected(stopCalled);
    }
    }
    
    
    //客户端代码:
    <h2>聊天系统</h2>
    <div class="container">
    @using (Html.BeginForm("login", "Chat", FormMethod.Post, new { @class = "form-inline" }))
    {
    <label>用户Id:</label>
    @Html.TextBox("userId", "", new { @class = "form-control" })
    <label>用户名:</label>
    @Html.TextBox("userName", "", new { @class = "form-control" })
    <input type="button" id="btnLogin" value="登录" class="btn btn-default" />
    }
    </div>
    <hr />
    <div class="container">
    <div class="col-md-3">
    <div class="panel panel-default">
    <div class="panel-heading">
    在线用户
    </div>
    <div class="panel-body">
    <ul id="userList">
    </ul>
    </div>
    </div>
    </div>
    <div class="col-md-8">
    <div class="panel panel-default">
    <div class="panel-heading">
    聊天内容
    </div>
    <div class="panel-body">
    <ul id="msgList" >
    </ul>
    </div>
    <div class="panel-footer">
    <label>消息To:</label> <label id="toUser"></label>
    @Html.TextBox("msg", "", new { @class = "form-control form-inline" })
    <input type="button" id="btnSend" value="发送" class="btn btn-default" />
    </div>
    </div>
    </div>
    </div>
    @section scripts{
    <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script>
    //用户点击(选择用户)
    function selectUser(li) {
    var connectionId = $(li).attr("cid");
    $('#toUser').text(connectionId);
    }
    $(function () {
    var chat = $.connection.Chat;
    
    //刷新在线列表
    chat.client.loadUser = function (allUsers) {
    $('#userList').html("");
    for (var i = 0; i < allUsers.length; i++) {
    var li = $('<li cid="' + allUsers[i].ConnectionId+'" onclick="selectUser(this)">' + allUsers[i].UserId + ':' + allUsers[i].UserName + '</li> ');
    $('#userList').append(li);
    }
    }
    //接收消息
    chat.client.receivePrivateMessage = function (from, msg) {
    var li = $("<li>来自:" + from + "<br/>" + msg + "</li>");
    $("#msgList").append(li);
    }
     
    $.connection.hub.start().done(function () {
    console.log("连接完成");
    //登录
    $('#btnLogin').click(function () {
    chat.server.login($("#userId").val(), $('#userName').val())
    })
    
    
    $('#btnSend').click(function () {
    chat.server.sendPrivateMessage($('#toUser').text(), $('#msg').val())
    })
    });
    })
    </script>
    实现
  • 相关阅读:
    mvc 注册脚本的其他方法
    如何将html代码转换为Xml并生成Dom树
    用TFIDF值来判断词的重要性
    oem key
    vs2010 下的ado.net 实体模型创建数据库时datetime 类型的问题
    asp.net mvc 动态注册脚本
    ASP.NET 中如何对生成的 HTML 内容流进行控制
    C# 子窗体调用父窗体的方法
    layui 弹出新页面
    winform excel导入进度条
  • 原文地址:https://www.cnblogs.com/shishixiang/p/14035227.html
Copyright © 2020-2023  润新知