最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

Asp.net使用SignalR实现聊天室的功能

来源:懂视网 责编:小采 时间:2020-11-27 22:37:46
文档

Asp.net使用SignalR实现聊天室的功能

Asp.net使用SignalR实现聊天室的功能:一、引言 在前一篇文章《Asp.net使用SignalR实现酷炫端对端聊天功能》中,我向大家介绍了如何实现实现端对端聊天的功能的,在这一篇文章中将像大家如何使用SignalR实现群聊这样的功能。 二、实现思路 要想实现群聊的功能,首先我们需要创建一个房间,然后每个
推荐度:
导读Asp.net使用SignalR实现聊天室的功能:一、引言 在前一篇文章《Asp.net使用SignalR实现酷炫端对端聊天功能》中,我向大家介绍了如何实现实现端对端聊天的功能的,在这一篇文章中将像大家如何使用SignalR实现群聊这样的功能。 二、实现思路 要想实现群聊的功能,首先我们需要创建一个房间,然后每个

一、引言
在前一篇文章《Asp.net使用SignalR实现酷炫端对端聊天功能》中,我向大家介绍了如何实现实现端对端聊天的功能的,在这一篇文章中将像大家如何使用SignalR实现群聊这样的功能。

二、实现思路
  要想实现群聊的功能,首先我们需要创建一个房间,然后每个在线用户可以加入这个房间里面进行群聊,我们可以为房间设置一个唯一的名字来作为标识。那SignalR类库里面是否有这样现有的方法呢?答案是肯定的。

// IGroupManager接口提供如下方法
// 作用:将连接ID加入某个组
// Context.ConnectionId 连接ID,每个页面连接集线器即会产生唯一ID
// roomName分组的名称
Groups.Add(Context.ConnectionId, roomName);

// 作用:将连接ID从某个分组移除
Groups.Remove(Context.ConnectionId, roomName);

// IHubConnectionContext接口提供了如下方法
// 调用客户端方法向房间内所有用户群发消息 
// Room:分组名称
// new string[0]:过滤(不发送)的连接ID数组
 Clients.Group(Room, new string[0]).clientMethod

  上面的代码也就是实现群聊的核心方法。Groups对象说白了也就是SignalR类库维护的一个列表对象而已,其实我们完全可以自己来维护一个Dictionary<string, List<string>>这个对象,创建一个房间的时候,我们将房间名称和进入房间的客户端的ConnectionId加入到这个字典里面,然后在聊天室里面点发送消息的时候,我们根据房间名查找到所有加入群聊的ConnectionId,然后调用Clients.Clients(IList<string> connectionIds)方法来将消息群发到每个客户端。以上也就是实现聊天室的原理。

三、使用SignalR实现聊天室的功能
理清楚了实现思路之后,接下来我们就看下具体的实现代码,同时大家也可以对照代码来对照前面的实现思路。
首先看下聊天室功能所涉及实体类的实现代码:

/// <summary>
 /// 用户类
 /// </summary>
 public class User
 {
 /// <summary>
 /// 用户Id
 /// </summary>
 public string UserId { get; set; }

 /// <summary>
 /// 用户的连接集合
 /// </summary>
 public List<Connection> Connections { get; set; }

 /// <summary>
 /// 用户房间集合,一个用户可以加入多个房间
 /// </summary>
 public List<ChatRoom> Rooms { get; set; }

 public User()
 {
 Connections = new List<Connection>();
 Rooms = new List<ChatRoom>();
 }
 }

 public class Connection
 {
 //连接ID
 public string ConnectionId { get; set; }

 //用户代理
 public string UserAgent { get; set; }
 //是否连接
 public bool Connected { get; set; } 
 }

 /// <summary>
 /// 房间类
 /// </summary>
 public class ChatRoom
 {
 // 房间名称
 public string RoomName { get; set; }

 // 用户集合
 public List<User> Users { get; set; }

 public ChatRoom()
 {
 Users = new List<User>();
 }
 }

 /// <summary>
 /// 上下文类,用来模拟EF中的DbContext
 /// </summary>
 public class ChatContext
 {
 public List<User> Users { get; set; }

 public List<Connection> Connections { get; set; }

 public List<ChatRoom> Rooms { get; set; }

 public ChatContext()
 {
 Users = new List<User>();
 Connections = new List<Connection>();
 Rooms = new List<ChatRoom>();
 }
 }


2. 接下来,让我们来看到集线器的实现:

[HubName("chatRoomHub")]
 public class GroupsHub : Hub
 {
 public static ChatContext DbContext = new ChatContext();

 #region IHub Members
 // 重写Hub连接事件
 public override Task OnConnected()
 {
 // 查询用户
 var user = DbContext.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);

 if (user == null)
 {
 user = new User
 {
 UserId = Context.ConnectionId
 };

 DbContext.Users.Add(user);
 }

 // 发送房间列表
 var items = DbContext.Rooms.Select(p => new {p.RoomName});
 Clients.Client(this.Context.ConnectionId).getRoomList(JsonHelper.ToJsonString(items.ToList()));
 return base.OnConnected();
 }

 // 重写Hub连接断开的事件
 public override Task OnDisconnected(bool stopCalled)
 {
 // 查询用户
 var user = DbContext.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);

 if (user != null)
 {
 // 删除用户
 DbContext.Users.Remove(user);

 // 从房间中移除用户
 foreach (var item in user.Rooms)
 {
 RemoveUserFromRoom(item.RoomName);
 }
 }
 return base.OnDisconnected(stopCalled);
 }

 #endregion 

 #region Public Methods

 // 为所有用户更新房间列表
 public void UpdateRoomList()
 {
 var itme = DbContext.Rooms.Select(p => new {p.RoomName});
 var jsondata = JsonHelper.ToJsonString(itme.ToList());
 Clients.All.getRoomlist(jsondata);
 }

 /// <summary>
 /// 加入聊天室
 /// </summary>
 public void JoinRoom(string roomName)
 {
 // 查询聊天室
 var room = DbContext.Rooms.Find(p => p.RoomName == roomName);

 // 存在则加入
 if (room == null) return;

 // 查找房间中是否存在此用户
 var isExistUser = room.Users.FirstOrDefault(u => u.UserId == Context.ConnectionId);

 // 不存在则加入
 if (isExistUser == null)
 {
 var user = DbContext.Users.Find(u => u.UserId == Context.ConnectionId);
 user.Rooms.Add(room);
 room.Users.Add(user);
 
 // 将客户端的连接ID加入到组里面
 Groups.Add(Context.ConnectionId, roomName);

 //调用此连接用户的本地JS(显示房间)
 Clients.Client(Context.ConnectionId).joinRoom(roomName);
 }
 else
 {
 Clients.Client(Context.ConnectionId).showMessage("请勿重复加入房间!");
 }
 }

 /// <summary>
 /// 创建聊天室
 /// </summary>
 /// <param name="roomName"></param>
 public void CreateRoom(string roomName)
 {
 var room = DbContext.Rooms.Find(a => a.RoomName == roomName);
 if (room == null)
 {
 var cr = new ChatRoom
 {
 RoomName = roomName
 };

 //将房间加入列表
 DbContext.Rooms.Add(cr);

 // 本人加入聊天室
 JoinRoom(roomName);
 UpdateRoomList();
 }
 else
 {
 Clients.Client(Context.ConnectionId).showMessage("房间名重复!");
 }
 }

 public void RemoveUserFromRoom(string roomName)
 {
 //查找房间是否存在
 var room = DbContext.Rooms.Find(a => a.RoomName == roomName);

 //存在则进入删除
 if (room == null)
 {
 Clients.Client(Context.ConnectionId).showMessage("房间名不存在!");
 return;
 }

 // 查找要删除的用户
 var user = room.Users.FirstOrDefault(a => a.UserId == Context.ConnectionId);
 // 移除此用户
 room.Users.Remove(user);
 //如果房间人数为0,则删除房间
 if (room.Users.Count <= 0)
 {
 DbContext.Rooms.Remove(room);
 }

 Groups.Remove(Context.ConnectionId, roomName);

 //提示客户端
 Clients.Client(Context.ConnectionId).removeRoom("退出成功!");
 }

 /// <summary>
 /// 给房间内所有的用户发送消息
 /// </summary>
 /// <param name="room">房间名</param>
 /// <param name="message">信息</param>
 public void SendMessage(string room, string message)
 {
 // 调用房间内所有客户端的sendMessage方法
 // 因为在加入房间的时候,已经将客户端的ConnectionId添加到Groups对象中了,所有可以根据房间名找到房间内的所有连接Id
 // 其实我们也可以自己实现Group方法,我们只需要用List记录所有加入房间的ConnectionId
 // 然后调用Clients.Clients(connectionIdList),参数为我们记录的连接Id数组。
 Clients.Group(room, new string[0]).sendMessage(room, message + " " + DateTime.Now);
 }
 #endregion 
}


3. 上面SignalR服务端的代码实现已经完成,接下来就让我们一起看看客户端视图的实现:

@{
 Layout = null;
}

<!DOCTYPE html>

<html>
<head>
 <meta name="viewport" content="width=device-width" />
 <title>Index</title>
 <script src="~/Scripts/jquery-2.2.2.min.js"></script>
 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
 <script src="~/Scripts/layer/layer.min.js"></script>
 <!--这里要注意,这是虚拟目录,也就是你在OWIN Startup中注册的地址-->
 <script src="https://www.gxlcms.com/signalr/hubs"></script>

 <script type="text/javascript">
 var chat;
 var roomcount = 0;
 
 $(function() {
 chat = $.connection.chatRoomHub;
 chat.client.showMessage = function(message) {
 alert(message);
 };
 chat.client.sendMessage = function(roomname, message) {
 $("#" + roomname).find("ul").each(function() {
 $(this).append('<li>' + message + '</li>');
 });
 };
 chat.client.removeRoom = function(data) {
 alert(data);
 };
 chat.client.joinRoom = function (roomname) {
 var html = '<div style="float:left; margin-left:360px; border:double; height:528px;width:493px" id="' + roomname + '" roomname="' + roomname + '"><button onclick="RemoveRoom(this)">退出</button>\
 ' + roomname + '房间\
 聊天记录如下:<ul>\
 </ul>\
 <textarea class="ChatCore_write" id="ChatCore_write" style="width:400px"></textarea> <button onclick="SendMessage(this)">发送</button>\
 </div>';
 $("#RoomList").append(html);
 };

 //注册查询房间列表的方法
 chat.client.getRoomlist = function(data) {
 if (data) {
 var jsondata = $.parseJSON(data);
 $("#roomlist").html(" ");
 for (var i = 0; i < jsondata.length; i++) {
 var html = ' <li>房间名:' + jsondata[i].RoomName + '<button roomname="' + jsondata[i].RoomName + '" onclick="AddRoom(this)">加入</button></li>';
 $("#roomlist").append(html);
 }
 }
 };
 // 获取用户名称。
 $('#username').html(prompt('请输入您的名称:', ''));

 $.connection.hub.start().done(function() {
 $('#CreatRoom').click(function() {
 chat.server.createRoom($("#Roomname").val());
 });
 });
 });
 
 function SendMessage(btn) {
 var message = $(btn).prev().val();
 var room = $(btn).parent();
 var username = $("#username").html();
 message = username + ":" + message;
 var roomname = $(room).attr("roomname");
 chat.server.sendMessage(roomname, message);
 $(btn).prev().val('').focus();
 }
 
 function RemoveRoom(btn) {
 var room = $(btn).parent();
 var roomname = $(room).attr("roomname");
 chat.server.removeUserFromRoom(roomname);
 }
 
 function AddRoom(roomname) {
 var data =$(roomname).attr("roomname");
 chat.server.joinRoom(data);
 }

 </script>
</head>
<body>
 <div>
 <div>名称:<p id="username"></p></div>
 输入房间名:
 <input type="text" value="聊天室1" id="Roomname" />
 <button id="CreatRoom">创建聊天室</button>
 </div>
 <div style="float:left;border:double">
 <div>房间列表</div>
 <ul id="roomlist"></ul>
 </div>
 <div id="RoomList">
 </div>
</body>
</html>

4. 经过上面3步,聊天室的功能就已经完成了,在看具体效果之前,这里附加一个帮助类的代码:

/// <summary>
 /// JSON 帮助类
 /// </summary>
 public class JsonHelper
 {
 /// <summary>
 /// 从一个对象信息生成Json字符串
 /// </summary>
 /// <param name="obj"></param>
 /// <returns></returns>
 public static string ToJsonString(object obj)
 {
 return JsonConvert.SerializeObject(obj);
 }

 /// <summary>
 /// 从Json字符串生成对象
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="jsonString"></param>
 /// <returns></returns>
 public static T ToObject<T>(string jsonString)
 {
 return JsonConvert.DeserializeObject<T>(jsonString);
 }
 }

四、运行结果  

接下来,就具体看看聊天室功能的运行效果,具体运行效果如下图所示:

源码下载:SignalRChatRoom

到这里,本篇的所有内容都介绍完了,接下来我一篇文章将实现如何使用SignalR来实现发图片的功能。

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

文档

Asp.net使用SignalR实现聊天室的功能

Asp.net使用SignalR实现聊天室的功能:一、引言 在前一篇文章《Asp.net使用SignalR实现酷炫端对端聊天功能》中,我向大家介绍了如何实现实现端对端聊天的功能的,在这一篇文章中将像大家如何使用SignalR实现群聊这样的功能。 二、实现思路 要想实现群聊的功能,首先我们需要创建一个房间,然后每个
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top