SignalR实现消息推送,包括私聊、群聊、在线所有人接收消息(源码)

小说:北京好的宝妈创业项目作者:海宗辛侯更新时间:2019-04-19字数:28086

SignalR实现消息推送,包括私聊、群聊、在线所有人接收消息(源码)


一、关于SignalR

        1、简介:Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。它出现的主要目的是实现服务器主动推送(Push)消息到客户端页面,这样客户端就不必重新发送请求或使用轮询技术来获取消息。

可访问其官方网站:https://github.com/SignalR/ 获取更多资讯。

   2、SignalR 的实现机制与 .NET WCF 或 Remoting 是相似的,都是使用远程代理来实现。在具体使用上,有两种不同目的的接口:PersistentConnection 和 Hubs,其中 PersistentConnection 是实现了长时间的 Javascript 轮询(类似于 Comet),Hub 是用来解决实时信息交换问题,它是利用 Javascript 动态载入执行方法实现的。SignalR 将整个连接,信息交换过程封装得非常漂亮,客户端与服务器端全部使用 JSON 来交换数据。

下面就 Hubs 接口的使用来讲讲整个流程:

  (1),在服务器端定义对应的 hub class;

  (2),在客户端定义 hub class 所对应的 proxy 类;

  (3),在客户端与服务器端建立连接(connection);

  (4),然后客户端就可以调用 proxy 对象的方法来调用服务器端的方法,也就是发送 request 给服务器端;

  (5),服务器端接收到 request 之后,可以针对某个/组客户端或所有客户端(广播)发送消息。

       以上这些都是关注大神们了解的。

二、具体使用

  1、建立一个mvc项目 SignalR通讯

  

  2、安装SignalR

    (1)、在SignalR通讯 项目下安装 SignalR(找到程序包管理器控制台,输入:Install-Package Microsoft.AspNet.SignalR)

        安装成功后系统会自动生成一个Scripts文件夹,里面存放对应的js文件,如图

  

  3、安装好环境以后。那么接下来我们就开始搭建我们的环境及编写相应的代码

    (1)、新建一个SignalR集线器ServerHub,如图

  

    并编写以下代码

 1 public class ServerHub : Hub
 2     {
 3         private static readonly char[] str =
 4         {
 5             "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
 6             "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
 7             "w", "x", "y", "z",
 8             "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
 9             "W", "X", "Y", "Z"
10         };
11 
12         /// <summary>
13         /// 消息发送接口
14         /// </summary>
15         /// <param name="message"></param>
16         public void SendMsg(string message)
17         {
18             var name = GenerateUserName(4);
19 
20             // 调用所有客户端的sendMessage方法
21             Clients.All.sendMessage(name, message);
22         }
23 
24         /// <summary>
25         /// 产生随机用户
26         /// </summary>
27         /// <param name="length">用户名长度</param>
28         /// <returns></returns>
29         public static string GenerateUserName(int length)
30         {
31             var newRandom = new StringBuilder(62);
32             var rd = new Random();
33             for (var i = 0; i < length; i++)
34             {
35                 newRandom.Append(str[rd.Next(62)]);
36             }
37             return newRandom.ToString();
38         }

 

    (2)、创建一个Startup类,(如果创建项目是有这个类。就不用添加了)添加代码如下 

 public void Configuration(IAppBuilder app)
        {
            // 配置集线器
            app.MapSignalR();
        }

    (3)、添加Home控制器及视图Index(此步骤不截图)

    (4)、添加Index视图代码  如下

 1 @{
 2     Layout = "~/Views/Shared/_Layout.cshtml";
 3     ViewBag.Title = "聊天窗口";
 4 }
 5 
 6 <h2>Index</h2>
 7 
 8 <div class="container">
 9     <input type="text" id="message" />
10     <input type="button" id="sendmessage" value="Send" />
11     <input type="hidden" id="displayname" />
12     <ul id="discussion"></ul>
13 </div>
14 
15 @section scripts
16 {
17 <script src="~/Scripts/jquery-1.6.4.min.js"></script>
18     <!--引用SignalR库. -->
19     <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>
20     <!--引用自动生成的SignalR 集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到 -->
21     <script src="~/signalr/hubs"></script>
22 
23     <script>
24         $(function () {
25             // 引用集线器代理
26             var chat = $.connection.serverHub;
27             // 定义服务器端调用的客户端sendMessage来显示新消息
28 
29             chat.client.sendMessage = function (name, message) {
30                 // 向页面添加消息
31                 $("#discussion").append("<li><strong>" + htmlEncode(name)
32                     + "</strong>: " + htmlEncode(message) + "</li>");
33             };
34 
35             // 设置焦点到输入框
36             $("#message").focus();
37             // 开始连接服务器
38             $.connection.hub.start().done(function () {
39                 $("#sendmessage").click(function () {
40                     // 调用服务器端集线器的SendMsg方法
41                     chat.server.sendMsg($("#message").val());
42                     // 清空输入框信息并获取焦点
43                     $("#message").val("").focus();
44                 });
45             });
46         });
47 
48         // 为显示的消息进行Html编码
49         function htmlEncode(value) {
50             var encodedValue = $("<div />").text(value).html();
51             return encodedValue;
52         }
53     </script>
54 }

  4、完成以上步骤之后,我们的SignalR算是简单的完成。让我们来看下制作结果吧

    (1)、如果出现如下错误,请删除红框里的代码

    

    成功之后的结果,如图

    

    你以为完了嘛?还没有,别急往下看

三、页面有优化及私聊、群聊、在线所有人接收消息的实现

  1、发送所有在线人员

    (1)、在layer官网下载layer前端js和ui(在我上一篇的文章中有下载地址,或者直接百度搜索layer),放到你的项目中,在这里我们就不直接说页面代码的编写部分,直接看下我们的效果图,如下

     

    (2)、在完成聊天之前。我们还需要做什么,对做登录,在这里自动生成的用户已经不能满足我们接下来的需求了(登录教程跳过)直接看登录成功过后的界面

    

    

    这样看起来就美观多了,其实在线所有人聊天的功能,就是刚刚我们实现那个功能是一样的,没有任何的变化(只是美观了下),看看聊天结果吧

    

      

  

    2、群聊

      (1)、首先我们的建一个群聊的实体(UserGroup)和房间实体(ChatRoom),如下图

       

 

    (2)、在我们建好的ServerHub类里编写如下代码(具体实现看源码)

  1 public static ChatContext DbContext = new ChatContext();
  2 
  3         // 重写Hub连接断开的事件  (断线时调用)
  4         public override Task OnDisconnected(bool stopCalled)
  5         {
  6             // 查询用户
  7             var user = DbContext.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);
  8 
  9             if (user != null)
 10             {
 11                 // 删除用户
 12                 DbContext.Users.Remove(user);
 13 
 14                 // 从房间中移除用户
 15                 foreach (var item in user.Rooms)
 16                 {
 17                     RemoveUserFromRoom(item.RoomName);
 18                 }
 19             }
 20             return base.OnDisconnected(stopCalled);
 21         }
 22         
 23         // 为所有用户更新房间列表
 24         public void UpdateRoomList()
 25         {
 26             var itme = DbContext.Rooms.Select(p => new { p.RoomName });
 27             var jsondata = JsonHelper.ToJsonString(itme.ToList());
 28             Clients.All.getRoomlist(jsondata);
 29         }
 30 
 31         /// <summary>
 32         /// 加入聊天室
 33         /// </summary>
 34         public void JoinRoom(string roomName)
 35         {
 36             // 查询聊天室
 37             var room = DbContext.Rooms.Find(p => p.RoomName == roomName);
 38 
 39             // 存在则加入
 40             if (room == null) return;
 41 
 42             // 查找房间中是否存在此用户
 43             var isExistUser = room.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);
 44 
 45             // 不存在则加入
 46             if (isExistUser == null)
 47             {
 48                 var user = DbContext.Users.Find(u => u.UserId == Context.ConnectionId);
 49                 user.Rooms.Add(room);
 50                 room.Users.Add(user);
 51 
 52                 // 将客户端的连接ID加入到组里面
 53                 Groups.Add(Context.ConnectionId, roomName);
 54 
 55                 //调用此连接用户的本地JS(显示房间)
 56                 Clients.Client(Context.ConnectionId).joinRoom(roomName);
 57             }
 58             else
 59             {
 60                 Clients.Client(Context.ConnectionId).showMessage("请勿重复加入房间!");
 61             }
 62         }
 63 
 64         /// <summary>
 65         /// 创建聊天室
 66         /// </summary>
 67         /// <param name="roomName"></param>
 68         public void CreateRoom(string roomName)
 69         {
 70             var room = DbContext.Rooms.Find(a => a.RoomName == roomName);
 71             if (room == null)
 72             {
 73                 var cr = new ChatRoom
 74                 {
 75                     RoomName = roomName
 76                 };
 77 
 78                 //将房间加入列表
 79                 DbContext.Rooms.Add(cr);
 80 
 81                 // 本人加入聊天室
 82                 JoinRoom(roomName);
 83                 UpdateRoomList();
 84             }
 85             else
 86             {
 87                 Clients.Client(Context.ConnectionId).showMessage("房间名重复!");
 88             }
 89         }
 90 
 91         public void RemoveUserFromRoom(string roomName)
 92         {
 93             //查找房间是否存在
 94             var room = DbContext.Rooms.Find(a => a.RoomName == roomName);
 95 
 96             //存在则进入删除
 97             if (room == null)
 98             {
 99                 Clients.Client(Context.ConnectionId).showMessage("房间名不存在!");
100                 return;
101             }
102 
103             // 查找要删除的用户
104             var user = room.Users.FirstOrDefault(a => a.UserId == Context.ConnectionId);
105             // 移除此用户
106             room.Users.Remove(user);
107             //如果房间人数为0,则删除房间
108             if (room.Users.Count <= 0)
109             {
110                 DbContext.Rooms.Remove(room);
111             }
112 
113             Groups.Remove(Context.ConnectionId, roomName);
114 
115             //提示客户端
116             Clients.Client(Context.ConnectionId).removeRoom("退出成功!");
117         }
118 
119         /// <summary>
120         /// 给房间内所有的用户发送消息
121         /// </summary>
122         /// <param name="room">房间名</param>
123         /// <param name="message">信息</param>
124         public void SendMessage(string room, string message)
125         {
126             // 调用房间内所有客户端的sendMessage方法
127             // 因为在加入房间的时候,已经将客户端的ConnectionId添加到Groups对象中了,所有可以根据房间名找到房间内的所有连接Id
128             // 其实我们也可以自己实现Group方法,我们只需要用List记录所有加入房间的ConnectionId
129             // 然后调用Clients.Clients(connectionIdList),参数为我们记录的连接Id数组。
130             Clients.Group(room, new string[0]).sendMessage(room, message + " " + DateTime.Now);
131         }

    (3)、在Home控制器里创建GroupUser视图并添加如下代码

  1 @{
  2     Layout = null;
  3 }
  4 
  5 <!DOCTYPE html>
  6 
  7 <html>
  8 <head>
  9     <meta name="viewport" content="width=device-width" />
 10     <title>Index</title>
 11     <script src="~/Scripts/jquery-1.10.2.min.js"></script>
 12     <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
 13     <script src="~/Scripts/layer/layer.js"></script>
 14     <!--这里要注意,这是虚拟目录,也就是你在OWIN Startup中注册的地址-->
 15     <script src="/signalr/hubs"></script>
 16 
 17     <script type="text/javascript">
 18         var chat;
 19         var roomcount = 0;
 20 
 21         $(function() {
 22             chat = $.connection.serverHub;
 23             chat.client.showMessage = function(message) {
 24                 alert(message);
 25             };
 26             chat.client.sendMessage = function(roomname, message) {
 27                 $("#" + roomname).find("ul").each(function() {
 28                     $(this).append("<li>" + message + "</li>");
 29                 });
 30             };
 31             chat.client.removeRoom = function(data) {
 32                 alert(data);
 33             };
 34             chat.client.joinRoom = function (roomname) {
 35                 var html = "<div style="float:left; margin-left:360px; border:double; height:528px;width:493px" id="" + roomname + "" roomname="" + roomname + ""><button onclick="RemoveRoom(this)">退出</button>
 36                                     " + roomname + "房间
 37                                                 聊天记录如下:<ul>
 38                                                 </ul>
 39                                     <textarea class="ChatCore_write" id="ChatCore_write" style="width:400px"></textarea> <button onclick="SendMessage(this)">发送</button>
 40                                     </div>";
 41                 $("#RoomList").append(html);
 42             };
 43 
 44             //注册查询房间列表的方法
 45             chat.client.getRoomlist = function(data) {
 46                 if (data) {
 47                     var jsondata = $.parseJSON(data);
 48                     $("#roomlist").html(" ");
 49                     for (var i = 0; i < jsondata.length; i++) {
 50                         var html = " <li>房间名:" + jsondata[i].RoomName + "<button roomname="" + jsondata[i].RoomName + "" onclick="AddRoom(this)">加入</button></li>";
 51                         $("#roomlist").append(html);
 52                     }
 53                 }
 54             };
 55             // 获取用户名称。
 56             $("#username").html(prompt("请输入您的名称:", ""));
 57 
 58             $.connection.hub.start().done(function() {
 59                 $("#CreatRoom").click(function() {
 60                     chat.server.createRoom($("#Roomname").val());
 61                 });
 62             });
 63         });
 64 
 65         function SendMessage(btn) {
 66             var message = $(btn).prev().val();
 67             var room = $(btn).parent();
 68             var username = $("#username").html();
 69             message = username + ":" + message;
 70             var roomname = $(room).attr("roomname");
 71             chat.server.sendMessage(roomname, message);
 72             $(btn).prev().val("").focus();
 73         }
 74 
 75         function RemoveRoom(btn) {
 76             var room = $(btn).parent();
 77             var roomname = $(room).attr("roomname");
 78             chat.server.removeUserFromRoom(roomname);
 79         }
 80 
 81         function AddRoom(roomname) {
 82             var data =$(roomname).attr("roomname");
 83             chat.server.joinRoom(data);
 84         }
 85 
 86     </script>
 87 </head>
 88 <body>
 89     <div>
 90         <div>名称:<p id="username"></p></div>
 91         输入房间名:
 92         <input type="text" value="聊天室1" id="Roomname" />
 93         <button id="CreatRoom">创建聊天室</button>
 94     </div>
 95     <div style="float:left;border:double">
 96         <div>房间列表</div>
 97         <ul id="roomlist"></ul>
 98     </div>
 99     <div id="RoomList">
100     </div>
101 </body>
102 </html>

    (4)、做好以上步骤之后,主要的功能已经实现,那么接下来我们看下效果 如下

    点击发送群聊之后出现如图所示

    

    并创建自己的用户名

    我们在创建自己的用户名之后,可以选择自己创建房间或者加入已有的房间,如下图

    

    

  3、私聊

 

    (1)、私聊我们在这里就不多说了。实现原理和群里差不多。都是找到对应的人员id就ok,直接上图看结果

    

    

源码请加qq群:460362190 里面有更多的开源项目哦,欢迎加入讨论

如果你还满意请点击关注和推荐,谢谢    

 

当前文章:http://cnsdbtzg.com/news/201901/18/content_67484.html

发布时间:2019-04-19 06:21:35

京东淘客查询 汕头正规工资日结 在知乎上回答问题可以挣钱? 苏宁易购怎么分享链接赚钱 租纯电动面包车做货拉拉能赚钱吗? cpa网校培训兼职 7天高炮贷可以不还吗 赚钱小项目加盟 淘宝哪个返利网最可信 3399高佣金联盟是真的

40091 74113 42360 14505 77911 7126731102 42900 82557

我要说两句: (0人参与)

发布