史上最全面的SignalR系列教程-五、SignalR 实现一对一聊天

一、概述

经过前面几篇文章javascript

史上最全面的SignalR系列教程-一、认识SignalRhtml

史上最全面的SignalR系列教程-二、SignalR 实现推送功能-永久链接类实现方式java

史上最全面的SignalR系列教程-三、SignalR 实现推送功能-集线器类实现方式jquery

史上最全面的SignalR系列教程-四、SignalR 自托管全解(使用Self-Host)-附各终端详细实例git

RDIFramework.NET敏捷开发框架经过SignalR技术整合即时通信(IM)github

咱们对SignalR算入门了,知道如何把SignalR合理应用到实际的项目中。前面的文章主要讲解的是SignalR的概念,托管方式,以及推送的功能。本篇主要讲解经过SignalR实现一对1、点对点的聊天。json

二、SignalR一对一聊天实现

2.一、 建立ASP.NET Mvc项目

新建一个空的ASP.NET Mvc项目,取名为:SignalROneToOne,以下图所示。为了整个系列的完整性,咱们直接在上一项目的基础上新增的一个测试项目,后面有项目的源码托管地址。浏览器

新建SignalROneToOne测试项目

2.二、安装Nuget包

建立好项目后,要使用SignalR,须要先安装SignalR包,能够经过程序包管理控制台输入包安装命令进行安装。服务器

Install-Package Microsoft.AspNet.SignalR
复制代码

也可使用界面方式,以下图所示。微信

安装SignalR包-Microsoft.AspNet.SignalR

2.三、一对一聊天后台代码实现###

向工程中添加HubConnections目录,在其中添加OneToOneHub.cs文件,以下图所示:

添加OneToOneHub

实现的主要步骤:

  1. 重写OnConnected链接方法和OnDisconnected断开方法。
  2. 使用SendMessage服务器端方法发送消息,GetName获取用户名。
  3. 客户端响应的提示返回信息方法,如Clients.Client(Context.ConnectionId).addMessage(message)

OneToOneHub代码内容以下:

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;

namespace SignalROneToOneDemo.Connections
{
    /// <summary>
    /// 用户实体类
    /// </summary>
    public class User
    {
        /// <summary>
        /// 链接ID
        /// </summary>
        [Key]
        public string ConnectionID { get; set; }

        /// <summary>
        /// 用户名称
        /// </summary>
        public string Name { get; set; }

        public User(string name, string connectionId)
        {
            this.Name = name;
            this.ConnectionID = connectionId;
        }
    }

    /// <summary>
    /// 点对点(一对一)聊天
    /// </summary>
    [HubName("chat")]
    public class OneToOneHub : Hub
    {
        public static List<User> users = new List<User>();

        //发送消息
        public void SendMessage(string connectionId, string message)
        {
            Clients.All.hello();
            var user = users.Where(s => s.ConnectionID == connectionId).FirstOrDefault();
            if (user != null)
            {
                Clients.Client(connectionId).addMessage(message + "" + DateTime.Now, Context.ConnectionId);
                //给本身发送,把用户的ID传给本身
                Clients.Client(Context.ConnectionId).addMessage(message + "" + DateTime.Now, connectionId);
            }
            else
            {
                Clients.Client(Context.ConnectionId).showMessage("该用户已离线...");
            }
        }

        [HubMethodName("getName")]
        public void GetName(string name)
        {
            //查询用户
            var user = users.SingleOrDefault(u => u.ConnectionID == Context.ConnectionId);
            if (user != null)
            {
                user.Name = name;
                Clients.Client(Context.ConnectionId).showId(Context.ConnectionId);
            }
            GetUsers();
        }

        /// <summary>
        /// 重写链接事件
        /// </summary>
        /// <returns></returns>
        public override Task OnConnected()
        {
            //查询用户
            var user = users.Where(u => u.ConnectionID == Context.ConnectionId).SingleOrDefault();
            //判断用户是否存在,不然添加集合
            if (user == null)
            {
                user = new User("", Context.ConnectionId);
                users.Add(user);
            }
            return base.OnConnected();
        }

        public override Task OnDisconnected(bool stopCalled)
        {
            var user = users.Where(p => p.ConnectionID == Context.ConnectionId).FirstOrDefault();
            //判断用户是否存在,存在则删除
            if (user != null)
            {
                //删除用户
                users.Remove(user);
            }
            GetUsers();//获取全部用户的列表
            return base.OnDisconnected(stopCalled);
        }

        //获取全部用户在线列表
        private void GetUsers()
        {
            var list = users.Select(s => new { s.Name, s.ConnectionID }).ToList();
            string jsonList = JsonConvert.SerializeObject(list);
            Clients.All.getUsers(jsonList);
        }
    }
}
复制代码

若是你是vs2015 的话添加的mvc项目 不进行身份验证的那种吧,必须得添加一个Startup 类。若是没有这个类请添加,否则的话项目运行不起来的,具体代码以下:

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(SignalROneToOneDemo.App_Start.SignalRQuickStart))]

namespace SignalROneToOneDemo.App_Start
{
    public class SignalRQuickStart
    {
        public void Configuration(IAppBuilder app)
        {
            // 有关如何配置应用程序的详细信息,请访问 https://go.microsoft.com/fwlink/?LinkID=316888
            // 配置集线器
            app.MapSignalR();
        }
    }
}
复制代码

2.四、一对一聊天前台代码实现###

@{
    ViewBag.Title = "OneToOneChat";
}

<h2>点对点(一对一)聊天实例代码</h2>

<div>
    <div>用户名称:<label id="userName"></label>(<label id="conId"></label>)</div>
    
    <div style="width:25%;border:1px solid #ff0000">
        <div>在线用户列表</div>
        <ul id="users"></ul>
    </div>
    <div id="userBox">
    </div>
</div>

@section scripts {
    <script src="~/Scripts/jquery-3.3.1.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.4.1.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script type="text/javascript">
        var clients = [];
        var chat;
        $(function () {        
            chat = $.connection.chat;
            console.info(chat);

            //显示提示方法
            chat.client.showMessage = function (message) {
                alert(message);
            }

            //注册显示信息的方法
            chat.client.addMessage = function (message, connectionId) {
                //debugger
                if ($.inArray(connectionId, clients)==-1) {
                    showWin(connectionId);
                }
      
                $("#messages" + connectionId).each(function () {
                    $(this).append('<li>'+message+'</li>');
                })
            }

            //注册显示全部用户的方法
            chat.client.getUsers = function (data) {            
                if (data) {
                    var json = $.parseJSON(data);                    
                    console.info(json);
                    $("#users").html(" ");
                    for (var i = 0; i < json.length; i++) {                        
                        var html = '<li>用户名:' + json[i].Name + '<input type="button" connectionId="' + json[i].ConnectionID + '" id="'  + json[i].ConnectionID + '" value="聊天"  onclick="userChat(this)" />' ;
                        $("#users").append(html);
                    }
                }
            }

            //注册显示推出聊天提示的方法
            chat.client.exitUser = function (data)
            {
                alert(data);
            }

            //注册显示我的信息的方法
            chat.client.showId = function (data)
            {
                $("#conId").html(data);
                clients.push(data);
            }

            //获取用户名称
            $('#userName').html(prompt('请输入您的名称', ''));
 
            //链接成功后获取本身的信息
            $.connection.hub.start().done(function () {
                chat.server.getName($('#userName').html());
            });
        });

        //开始聊天
        function userChat(obj)
        {
            var connectionId = $(obj).attr('connectionId');
            showWin(connectionId);
        }

        function showWin(connectionId)
        { 
            clients.push(connectionId);
            var html = '<div style="float:left;margin-top:5px;margin-right: 5px;margin-bottom: 5px;border:1px solid #ff0000" id="' + connectionId + '" connectionId="' + connectionId + '">' + connectionId + '"的房间聊天记录以下:<button onclick="exitChat(this)">退出</button><ul id="messages' + connectionId + '"></ul><input type="text" /> <button onclick="sendMessage(this)">发送</button></div>';
            $("#userBox").append(html);
        }

        function exitChat(btnObj)
        {          
            $(btnObj).parent().remove();
            chat.server.exitChat(connectionId);
        }

        //发送消息
        function sendMessage(data)
        {
            var message = $(data).prev().val();
            var  userObj = $(data).parent();
            var username = $("#userName").html();
            message = username + ":" + message;
            console.info($(userObj).attr("connectionId"));
            var targetConnectionId = $(userObj).attr("connectionId");
            chat.server.sendMessage(targetConnectionId, message);
            $(data).prev().val("");
        }
    </script>
}
复制代码

三、效果展现

一对一聊天效果展现

到此,一个SignalR一对一(点对点)聊天例子就完成了,下面咱们简单的对代码做下分析:

Clients.Client(connectionId).addMessage():做用客户端注册addMessage方法,向指定链接Id的客户端发送消息。因为一对一聊天发送的消息也应该回发给本身,因此回发给本身链接的Id能够经过Context.ConnectionId来获取。固然也也可使用Client.Caller()代替Client.Client(Context.ConnectionId)方法直接发送。

Client.Clients(IList connectionIds):同时向多个ConnectionId发送消息,相似于QQ上@好友的功能。

经过浏览器F12咱们能够看到SignalR给咱们生成的方法:

F12Hubs代码效果

能够看到咱们服务端开发的两个方法,须要特别说明的是服务器端的方法名在客户端调用都约定第一个字母为小写,固然咱们也能够经过方法名上加特性HubMethodName进行标识处理。

四、代码下载

实例源码能够移步github下载,地址:github.com/yonghu86/Si…

五、参考文章


一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,你们能够经过下面的地址了解详情。

RDIFramework.NET官方网站:www.rdiframework.net/

RDIFramework.NET官方博客:blog.rdiframework.net/

同时须要说明的,之后的全部技术文章以官方网站为准,欢迎你们收藏!

RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!

欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。

扫描二维码当即关注

微信号:guosisoft
相关文章
相关标签/搜索