史上最全面的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
相關文章
相關標籤/搜索