0

0

Asp.net SignalR的应用并实现群聊功能的实例详解

Y2J

Y2J

发布时间:2017-04-27 15:58:45

|

1991人浏览过

|

来源于php中文网

原创

这篇文章主要为大家分享了asp.net signalr应用并实现群聊功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。(来自官方介绍。)

SignalR官网

 -1、写这篇的原因

在上篇文章B/S(Web)实时通讯解决方案中,并没有详情介绍SignalR,所以另起一篇专门介绍SignalR,本文的侧重点是Hub功能。 

0、先看最终实现效果

github.com/Emrys5/SignalRGroupChatDemo

 1、准备工作

1.1、在NuGet上首先下载SignalR的包。

1.2、配置Owin与SignalR

1.2.1、新建Startup类,注册SignalR

public class Startup
 {
 public void Configuration(IAppBuilder app)
 {
  app.MapSignalR();
 }
 }

然后在web.config配置Startup类,在configuration=>appSettings节点中添加

1.2.2、在页面引入SignalR的js

1、由于SignalR前端是基于jQuery的,所以页面需引入jQuery。

2、引入SignalR的js 。

3、引入最重要的hubs js,这个js其实并不存在,SignalR会反射获取所有供客户端调用的方法放入hubs js中。


 

1.2.3、新建GroupChatHub类,并继承Hub抽象类

在hub类中的方法就是提供给客户端调用的js方法。

在js中就可以用signalr调用SendMsg。

[HubName("simpleHub")]
 public class SimpleHub : Hub
 { 
 public void SendMsg(string msg)
 {
 }
 }

这样基本上前期准备工作就做完了,后面就是具体的操作。

2、原理与简单的编程

其实原理如果简单点理解就很简单,因为http是无状态的,所以每次请求以后都会与服务器断开链接,那就是说客户端可以很容易找到服务器,但是服务器如果想给你客户端发送消息就比较麻烦,如果不明白的可以参考上一篇文章B/S(Web)实时通讯解决方案。

SignalR就很好的解决了这个问题,也就说实现了实现了浏览器与服务器的全双工通信。

2.1、客户端至服务端(B=>S)

客户端代码

服务端代码

[HubName("simpleHub")]
 public class SimpleHub : Hub
 {
 public void SendMsg(string msg)
 {
  // 获取链接id
  var connectionId = Context.ConnectionId; 
  // 获取cookie
  var cookie = Context.RequestCookies;

 }

 }

其中SimpleHub就是我们定义的继承Hub类SimpleHub,然后我们可以用特性HubName进行重命名。

然后开始链接。

在链接完成以后,我们就可以调用在SimpleHub类中调用的方法。这就就很简单的实现了客户端至服务端发送消息。

bee餐饮点餐外卖小程序
bee餐饮点餐外卖小程序

bee餐饮点餐外卖小程序是针对餐饮行业推出的一套完整的餐饮解决方案,实现了用户在线点餐下单、外卖、叫号排队、支付、配送等功能,完美的使餐饮行业更高效便捷!功能演示:1、桌号管理登录后台,左侧菜单 “桌号管理”,添加并管理你的桌号信息,添加以后在列表你将可以看到 ID 和 密钥,这两个数据用来生成桌子的二维码2、生成桌子二维码例如上面的ID为 308,密钥为 d3PiIY,那么现在去左侧菜单微信设置

下载

我们还可以在Context中获取我们想要的东西,比如链接id,cookie等。

2.2、服务端至客户端(S=>B)

服务端代码

[HubName("simpleHub")]
 public class SimpleHub : Hub
 {
 public void SendMsg(string msg)
 {
  Clients.All.msg("发送给客户端的消息"); 
 }
 }

客户端代码

这里演示了怎么发送消息至客户端,也是SignalR比较重要的功能,这里有两个问题需要解决。

问题一、这里是发送消息给所有连着的客户端,如果是单个客户端或者是一批客户端应该怎么发送。

问题二、我们在调用msg给个客户端发送消息时是在接收消息以后做的反馈,然后发送消息给客户端,这样就很类似ajax了,服务端并没有主动给客户端发送消息。

解决:

问题一、Clients可以给特性的一群或者一个客户端发送消息

// 所有人
Clients.All.msg("发送给客户端的消息"); 
// 特定 cooectionId
Clients.Client("connectionId").msg("发送给客户端的消息");
// 特定 group
Clients.Group("groupName").msg("发送给客户端的消息");

这是比较常用的三个,当然还有很多,比如AllExcept,Clients。

在SignalR2.0中还添加了Others,OthersInGroup,OthersInGroups等等。

问题二、我们可以在需要发送消息的地方调用GlobalHost.ConnectionManager.GetHubContext().Clients中获取Clients。获取Clients并发送消息我们最好写成单例模式,因为这种需求很符合单例,群聊中有详细的代码。

3、SignalR实现群聊

以上的介绍和代码已经可以实现b=>s和s=>b了,那实现群聊和单独聊天就比较简单了。

由于功能比较简单,所有我把用户名存到了cookie里,也就说第一次进来时需要设置cookie。

还有就是在hub中要实现OnConnected、OnDisconnected和OnReconnected,然后在方法中设置用户和connectionid和统计在线用户,以便聊天使用。

hub代码

/// 
 /// SignalR Hub 群聊类
 /// 
 [HubName("groupChatHub")] // 标记名称供js调用
 public class GroupChatHub : Hub
 {
 /// 
 /// 用户名
 /// 
 private string UserName
 {
  get
  {
  var userName = Context.RequestCookies["USERNAME"];
  return userName == null ? "" : HttpUtility.UrlDecode(userName.Value);
  }
 }

 /// 
 /// 在线用户
 /// 
 private static Dictionary _onlineUser = new Dictionary();

 /// 
 /// 开始连接
 /// 
 /// 
 public override Task OnConnected()
 {
  Connected();
  return base.OnConnected();
 }


 /// 
 /// 重新链接
 /// 
 /// 
 public override Task OnReconnected()
 {
  Connected();
  return base.OnReconnected();
 }


 private void Connected()
 {
  // 处理在线人员
  if (!_onlineUser.ContainsKey(UserName)) // 如果名称不存在,则是新用户
  {

  // 加入在线人员
  _onlineUser.Add(UserName, 1);

  // 向客户端发送在线人员
  Clients.All.publshUser(_onlineUser.Select(i => i.Key));

  // 向客户端发送加入聊天消息
  Clients.All.publshMsg(FormatMsg("系统消息", UserName + "加入聊天"));
  }
  else
  {
  // 如果是已经存在的用户,则把在线链接的个数+1
  _onlineUser[UserName] = _onlineUser[UserName] + 1;
  }

  // 加入Hub Group,为了发送单独消息
  Groups.Add(Context.ConnectionId, "GROUP-" + UserName);
 }


 /// 
 /// 结束连接
 /// 
 /// 
 /// 
 public override Task OnDisconnected(bool stopCalled)
 {
  // 人员链接数-1
  _onlineUser[UserName] = _onlineUser[UserName] - 1;

  // 判断是否断开了所有的链接
  if (_onlineUser[UserName] == 0)
  {
  // 移除在线人员
  _onlineUser.Remove(UserName);

  // 向客户端发送在线人员
  Clients.All.publshUser(_onlineUser.Select(i => i.Key));

  // 向客户端发送退出聊天消息
  Clients.All.publshMsg(FormatMsg("系统消息", UserName + "退出聊天"));
  }

  // 移除Hub Group
  Groups.Remove(Context.ConnectionId, "GROUP-" + UserName);
  return base.OnDisconnected(stopCalled);
 }

 /// 
 /// 发送消息,供客户端调用
 /// 
 /// 用户名,如果为0,则是发送给所有人
 /// 消息
 public void SendMsg(string user, string msg)
 {
  if (user == "0")
  {
  // 发送给所有用户消息
  Clients.All.publshMsg(FormatMsg(UserName, msg));
  }
  else
  {
  //// 发送给自己消息
  //Clients.Group("GROUP-" + UserName).publshMsg(FormatMsg(UserName, msg));

  //// 发送给选择的人员
  //Clients.Group("GROUP-" + user).publshMsg(FormatMsg(UserName, msg));


  // 发送给自己消息
  Clients.Groups(new List { "GROUP-" + UserName, "GROUP-" + user }).publshMsg(FormatMsg(UserName, msg));

  }
 }


 /// 
 /// 格式化发送的消息
 /// 
 /// 
 /// 
 /// 
 private dynamic FormatMsg(string name, string msg)
 {
  return new { Name = name, Msg = HttpUtility.HtmlEncode(msg), Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") };
 }
 }

js代码

html代码

群聊系统(1人在线):@ViewBag.UserName


    这样就消息了群聊和发送给特定的人聊天功能。

    3.1、封装主动发送消息的单例

    /// 
     /// 主动发送给用户消息,单例模式
     /// 
     public class GroupChat
     {
     /// 
     /// Clients,用来主动发送消息
     /// 
     private IHubConnectionContext Clients { get; set; }
    
     private readonly static GroupChat _instance = new GroupChat(GlobalHost.ConnectionManager.GetHubContext().Clients);
    
     private GroupChat(IHubConnectionContext clients)
     {
      Clients = clients;
     }
    
     public static GroupChat Instance
     {
      get
      {
      return _instance;
      }
     }
    
    
     /// 
     /// 主动给所有人发送消息,系统直接调用
     /// 
     /// 
     public void SendSystemMsg(string msg)
     {
      Clients.All.publshMsg(new { Name = "系统消息", Msg = msg, Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") });
     }
     }

    如果需要发送消息,直接调用SendSystemMsg即可。

    GroupChat.Instance.SendSystemMsg("消息");

     4、结语

    啥也不说了直接源码

    github.com/Emrys5/SignalRGroupChatDemo

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    C++ 设计模式与软件架构
    C++ 设计模式与软件架构

    本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

    14

    2026.01.30

    c++ 字符串格式化
    c++ 字符串格式化

    本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

    9

    2026.01.30

    java 字符串格式化
    java 字符串格式化

    本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

    12

    2026.01.30

    python 字符串格式化
    python 字符串格式化

    本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

    4

    2026.01.30

    java入门学习合集
    java入门学习合集

    本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

    20

    2026.01.29

    java配置环境变量教程合集
    java配置环境变量教程合集

    本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

    18

    2026.01.29

    java成品学习网站推荐大全
    java成品学习网站推荐大全

    本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

    19

    2026.01.29

    Java字符串处理使用教程合集
    Java字符串处理使用教程合集

    本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

    3

    2026.01.29

    Java空对象相关教程合集
    Java空对象相关教程合集

    本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

    6

    2026.01.29

    热门下载

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

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    ASP.NET参考手册
    ASP.NET参考手册

    共0课时 | 0人学习

    传播智客ASP.NET中级系列视频教程
    传播智客ASP.NET中级系列视频教程

    共33课时 | 6.4万人学习

    传播智客ASP.NET高级系列视频教程
    传播智客ASP.NET高级系列视频教程

    共34课时 | 6.3万人学习

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

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