0

0

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

高洛峰

高洛峰

发布时间:2016-12-24 14:20:38

|

2156人浏览过

|

来源于php中文网

原创

一、引言
在前一篇文章《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>这个对象,创建一个房间的时候,我们将房间名称和进入房间的客户端的ConnectionId加入到这个字典里面,然后在聊天室里面点发送消息的时候,我们根据房间名查找到所有加入群聊的ConnectionId,然后调用Clients.Clients(IList connectionIds)方法来将消息群发到每个客户端。以上也就是实现聊天室的原理。

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

/// 
 /// 用户类
 /// 
 public class User
 {
  /// 
  /// 用户Id
  /// 
  public string UserId { get; set; }
 
  /// 
  /// 用户的连接集合
  /// 
  public List Connections { get; set; }
 
  /// 
  /// 用户房间集合,一个用户可以加入多个房间
  /// 
  public List Rooms { get; set; }
 
  public User()
  {
   Connections = new List();
   Rooms = new List();
  }
 }
 
 public class Connection
 {
  //连接ID
  public string ConnectionId { get; set; }
 
  //用户代理
  public string UserAgent { get; set; }
  //是否连接
  public bool Connected { get; set; }
 }
 
  /// 
 /// 房间类
 /// 
 public class ChatRoom
 {
  // 房间名称
  public string RoomName { get; set; }
 
  // 用户集合
  public List Users { get; set; }
 
  public ChatRoom()
  {
   Users = new List();
  }
 }
 
 /// 
 /// 上下文类,用来模拟EF中的DbContext
 /// 
 public class ChatContext
 {
  public List Users { get; set; }
 
  public List Connections { get; set; }
 
  public List Rooms { get; set; }
 
  public ChatContext()
  {
   Users = new List();
   Connections = new List();
   Rooms = new List();
  }
 }

   


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);
  }
 
  /// 
  /// 加入聊天室
  /// 
  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("请勿重复加入房间!");
   }
  }
 
  /// 
  /// 创建聊天室
  /// 
  /// 
  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("退出成功!");
  }
 
  /// 
  /// 给房间内所有的用户发送消息
  /// 
  /// 房间名
  /// 信息
  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;
}
 

 


 
 Index
 
 
 
 
 
 
 


 

名称:

输入房间名:

房间列表

天天企业网站管理系统简繁英三语版2.8 Build 20180128
天天企业网站管理系统简繁英三语版2.8 Build 20180128

天天企业网站管理系统简繁英三语版(TianTian CMS)是由天天网络科技工作室开发的多语言企业网站源码,主要功能模块有企业信息、新闻动态、产品展示、资源下载、视频中心、人才招聘、支持服务、会员中心、留言反馈等。会员可用QQ快速登录。可在线订购产品和实时支付。运行环境:ASP+ACCESS(或ms sql),采用DIV+CSS构架,使网页整洁美观。代码用UTF-8编码,通用性比较好,适合国内外服

下载

       

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

    /// 
     /// JSON 帮助类
     /// 
     public class JsonHelper
     {
      /// 
      /// 从一个对象信息生成Json字符串
      /// 
      /// 
      /// 
      public static string ToJsonString(object obj)
      {
       return JsonConvert.SerializeObject(obj);
      }
     
      /// 
      /// 从Json字符串生成对象
      /// 
      /// 
      /// 
      /// 
      public static T ToObject(string jsonString)
      {
       return JsonConvert.DeserializeObject(jsonString);
      }
     }

       

    四、运行结果  

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

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

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

    更多Asp.net使用SignalR实现聊天室的功能相关文章请关注PHP中文网!

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

    相关专题

    更多
    Golang gRPC 服务开发与Protobuf实战
    Golang gRPC 服务开发与Protobuf实战

    本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

    4

    2026.01.15

    公务员递补名单公布时间 公务员递补要求
    公务员递补名单公布时间 公务员递补要求

    公务员递补名单公布时间不固定,通常在面试前,由招录单位(如国家知识产权局、海关等)发布,依据是原入围考生放弃资格,会按笔试成绩从高到低递补,递补考生需按公告要求限时确认并提交材料,及时参加面试/体检等后续环节。要求核心是按招录单位公告及时响应、提交材料(确认书、资格复审材料)并准时参加面试。

    28

    2026.01.15

    公务员调剂条件 2026调剂公告时间
    公务员调剂条件 2026调剂公告时间

    (一)符合拟调剂职位所要求的资格条件。 (二)公共科目笔试成绩同时达到拟调剂职位和原报考职位的合格分数线,且考试类别相同。 拟调剂职位设置了专业科目笔试条件的,专业科目笔试成绩还须同时达到合格分数线,且考试类别相同。 (三)未进入原报考职位面试人员名单。

    36

    2026.01.15

    国考成绩查询入口 国考分数公布时间2026
    国考成绩查询入口 国考分数公布时间2026

    笔试成绩查询入口已开通,考生可登录国家公务员局中央机关及其直属机构2026年度考试录用公务员专题网站http://bm.scs.gov.cn/pp/gkweb/core/web/ui/business/examResult/written_result.html,查询笔试成绩和合格分数线,点击“笔试成绩查询”按钮,凭借身份证及准考证进行查询。

    6

    2026.01.15

    Java 桌面应用开发(JavaFX 实战)
    Java 桌面应用开发(JavaFX 实战)

    本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

    63

    2026.01.14

    php与html混编教程大全
    php与html混编教程大全

    本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

    34

    2026.01.13

    PHP 高性能
    PHP 高性能

    本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

    73

    2026.01.13

    MySQL数据库报错常见问题及解决方法大全
    MySQL数据库报错常见问题及解决方法大全

    本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

    20

    2026.01.13

    PHP 文件上传
    PHP 文件上传

    本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

    31

    2026.01.13

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    直播系统及多人直播聊天室系统
    直播系统及多人直播聊天室系统

    共6课时 | 1.1万人学习

    尚学堂java开发聊天室视频教程
    尚学堂java开发聊天室视频教程

    共16课时 | 4.2万人学习

    第十一期_综合实战
    第十一期_综合实战

    共115课时 | 20.7万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号