热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用ASP.NETSignalR实现一个简单的聊天室

前言距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多。青春是短暂的,知识是无限的。要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人。今天

 前言

  距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多。青春是短暂的,知识是无限的。要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人。今天写个随笔小结记录一下。

 什么是SignalR?

  陌生的关键字,百度科普一下,什么是SignalR?ASP .NET SignalR 是一个ASP .NET 下的类库,可以在web中实现实时通信。服务器端可以将消息自动推送到已连接的客户端。官方网站SignalR介绍写得很详细, http://www.asp.net/signalr/overview/getting-started/tutorial-getting-started-with-signalr  官网是英文的,如果像我一样看英文看的头疼的,可以像我一样试试把url中的  “en-us”改为 “zh-cn” 刷新即变成中文的了,

技术分享图片

 

先看几个我做的效果图

技术分享图片

技术分享图片

技术分享图片

这个聊天室,刚开始前端我用的是BootStrap,Css和页面布局我是拷贝了网上的别人改过的,直接搬过来用的,具体是哪里找的忘记了。。  QAQ。在此谢过了。聊天室中我实现了登录,公共聊天,组件群聊,私聊,消息推送,保存聊天记录等等功能。后来基本功能实现了后,前端我使用vue.js+webapi前后端分离了。

新建项目,SignalR入门

1)新建一个asp.net web项目,类型为MVC,取名为SignalRChat,然后在引用中添加NuGet浏览中安装SignalR。或者在工具栏中,程序包管理控制台输入如下语句安装SignalR:install-package Microsoft.AspNet.SignalR

2)  添加hub文件
 项目右键新建文件一个文件夹取名为Hubs,在该文件夹下新建一个Signalr集线类(v2),ChatHub类得上面自定义HubName,然后在 startup文件里配置hub路径,默认得HubName是该类名称开头字母小写

3)  建立一个 OWIN Startup 类来配置应用.

技术分享图片技术分享图片
 1 [assembly: OwinStartup(typeof(SignalRChat.Startup))]
 2 namespace SignalRChat   
 3 {
 4     public class Startup
 5     {
 6         public void Configuration(IAppBuilder app)
 7         {
 8             app.MapSignalR();
 9         }
10     }
11 }
View Code

 我的项目结构

技术分享图片

Scripts中我只保留了必需用到的几个js,其他不必要的都删除,Model放实体类,common放公共类。SignalRContext类是自定义的一个类,用户保存在线用户的一些连接信息和房间信息等。没有涉及数据库,登陆数据是手动模拟造的数据。

重点在创建的ChatHub集线器中

技术分享图片技术分享图片
 1  [HubName("chatHub")]
 2     public class ChatHub : Hub
 3     {
 4         #region 全局对象
 5         protected static List userInfoList = new List();
 6         protected static SignalRContext DbCOntext= new SignalRContext();
 7         protected static List chatHistoryList = new List();
 8         #endregion
 9 
10         #region 连接
11       
12         /// 
13         /// 客户端重连接时
14         /// 
15         /// 
16         public override Task OnConnected()
17         {
18             AddUserGroup();//添加用户组
19             UpdateAllRoomList();//更新房间列表
20 
21             return base.OnConnected();
22         }
23         /// 
24         /// 断线
25         /// 
26         /// 
27         /// 
28         public override Task OnDisconnected(bool stopCalled)
29         {
30             return base.OnDisconnected(stopCalled);
31         }
32         #endregion
View Code

1)前端引用自动生成得集线器代理对象

var chat = $.connection.chatHub;注意红色标明得注意取 HubName中得名称,如果hubname没注释,就取集线器类中得类名首字母小写。

 2) 开始连接服务器
   $.connection.hub.start().done(function () {  });

公共聊天方法

技术分享图片技术分享图片
 1  #region 公共聊天
 2 
 3         /// 
 4         /// 公共聊天
 5         /// 
 6         /// 
 7         /// 
 8         public void PublicSendMsg(string message, string userId)
 9         {
10             var user = userInfoList.FirstOrDefault(x => x.UserID == userId);
11             Clients.All.sendPublicMessage(user.UserID, user.UserName, message);
12             AddChatHistory(ChatType.PubChat,user.UserName, message, user.UserID,"");//添加历史记录
13         }
14         #endregion
View Code

一对一聊天方法

技术分享图片技术分享图片
 1  /// 
 2         /// 发送私聊消息
 3         /// 
 4         /// 发送名称
 5         /// 用户id
 6         /// 消息
 7         public void SendPrivateMsg(string sendName, string userId, string message)
 8         {
 9             var toUser = userInfoList.FirstOrDefault(x => x.UserID == userId);//接收用户信息
10             var fromUser = userInfoList.FirstOrDefault(x => x.COnnectionId== Context.ConnectionId);//发送用户信息
11             if (toUser != null && fromUser != null)
12             {
13                 Clients.Caller.showMsgToPages(fromUser.UserID, sendName, message);
14                 if (fromUser.UserID != userId)//判断是否是自己给自己发消息
15                 {
16                     Clients.Client(toUser.ConnectionId).remindMsg(fromUser.UserID, fromUser.UserName,message);
17                 }
18                 AddChatHistory(ChatType.PriChat, sendName, message, fromUser.UserID, userId, "");
19             }
20         }
View Code

多对多聊天,群聊方法 

技术分享图片技术分享图片
 1  /// 
 2         /// 创建聊天室
 3         /// 
 4         /// 
 5         public void CreateRoom(string roomName)
 6         {
 7             var room = DbContext.Rooms.Find(x => x.RoomName == roomName);
 8             if (room == null)
 9             {
10                 var rom = new ChatRoom
11                 {
12                     RoomName = roomName,
13                     RoomId = Guid.NewGuid().ToString().ToUpper()
14                 };
15                 DbContext.Rooms.Add(rom);//加入房间列表
16                 UpdateAllRoomList();//更新房间列表
17                 Clients.Client(Context.ConnectionId).showGroupMsg("success");
18             }
19             else
20             {
21                 Clients.Client(Context.ConnectionId).showGroupMsg("error");
22             }
23         }
24 
25         /// 
26         ///加入聊天室
27         /// 
28         public void JoinRoom(string roomId,string current_Id)
29         {
30             // 查询聊天室,
31             var room = DbContext.Rooms.Find(x => x.RoomId == roomId.Trim());
32             var u = userInfoList.Find(x => x.UserID == current_Id);
33             if (room != null)
34             {
35                 //检测该用户是否存在在该房间
36                 var isExistUser = room.Users.Find(x => x.UserCOnnectionId== Context.ConnectionId);
37                 if (isExistUser == null)
38                 {
39                     var user = DbContext.Users.Find(x => x.UserCOnnectionId== Context.ConnectionId);
40                     user.Rooms.Add(room);//用户信息中加入房间信息
41                     room.Users.Add(user);//房间信息中加入用户信息
42                     Groups.Add(Context.ConnectionId, room.RoomName);//添加到组中
43                     Clients.Group(room.RoomName, new string[0]).showSysGroupMsg(u.UserName);
44                 }
45             }
46             else
47             {
48                 Clients.Client(Context.ConnectionId).showMessage("该群组不存在");
49             }
50         }
51 
52         /// 
53         /// 给指定房间内的所有用户发消息
54         /// 
55         /// 房间名
56         /// 消息
57         public void SendMessageByRoom(string roomId, string current_Id, string message)
58         {
59             var room = DbContext.Rooms.FirstOrDefault(x=>x.RoomId==roomId);
60             var user = userInfoList.Find(x => x.UserID == current_Id);
61             if (room != null && user != null)
62             {
63                 Clients.Group(room.RoomName, new string[0]).showGroupByRoomMsg(user.UserName,room.RoomId, message);
64                 AddChatHistory(ChatType.GroChat, user.UserName, message, user.UserID, "", room.RoomId);
65             }
66         }
67 
68         /// 
69         /// 退出房间
70         /// 
71         public void RemoveRoom(string roomId)
72         {
73             var room = DbContext.Rooms.Find(x => x.RoomId == roomId);
74             if (room != null)
75             {
76                 var user = DbContext.Users.Find(x => x.UserCOnnectionId== Context.ConnectionId);
77                 room.Users.Remove(user);//从房间里移除该用户
78                 if (room.Users.Count <= 0)
79                 {
80                     DbContext.Rooms.Remove(room);//如果房间里没人了,删除该房间
81                 }
82                 Groups.Remove(Context.ConnectionId, room.RoomName);
83                 UpdateAllRoomList();//更新房间列表
84                 Clients.Client(Context.ConnectionId).removeRoom();
85             }
86             else
87             {
88                 Clients.Client(Context.ConnectionId).showMessage("该房间不存在");
89             }
90         }
View Code

 前端调用后台代码,使用  chat.server.方法名(参数1,参数2) 例如

技术分享图片技术分享图片
 1   // 开始连接服务器
 2         $.connection.hub.start().done(function () {
 3         $(#btnSend).click(function () {
 4             var msg = $(#textMessage).val().trim();
 5             if (msg == "" || msg == undefined || msg == null) {
 6                 alert("请输入聊天信息");
 7                 $(#textMessage).focus();
 8             } else {
 9                 // 调用服务器端集线器的Send方法
10                 chat.server.publicSendMsg(msg, current_userid);
11                 // 清空输入框信息并获取焦点
12                 $(#textMessage).val(‘‘).focus();
13             }
14         });
View Code

后台调用前端的代码。使用 chat.client.方法名。例如

技术分享图片技术分享图片
1  //显示新用户加入消息
2         chat.client.showJoinMessage = function (nickName) {
3         $("#js-panel-content").append(
+ nickName + 加入了聊天
); 4 }
View Code

 最后还有个保存和获取聊天记录的主要方法

 1        // 
 2         /// 获取历史记录
 3         /// 
 4         /// 消息类型0公共聊天,1好友,2群
 5         /// 接收者id
 6         /// 发送方id
 7         /// 房间id
 8         public void GetChatHistory(int chatType =(int)ChatType.PubChat,string toId="", string frmId="",string roomId="")
 9         {
10             var list = chatHistoryList;
11             var type = (ChatType)chatType;
12             switch (type)
13             {
14                 case ChatType.PubChat:
15                     list = chatHistoryList.Where(x => x.ChatType == type).ToList();
16                     break;
17                 case ChatType.PriChat:
18                     //自己发送给对方的,和对方发给自己的数据集合
19                     list = chatHistoryList.Where(x => x.ChatType == type && ((x.toId == toId && x.frmId == frmId) || (x.toId == frmId && x.frmId == toId))).ToList();
20                     break;
21                 case ChatType.GroChat:
22                     list = chatHistoryList.Where(x => x.ChatType == type && x.RoomId == roomId).ToList();
23                     break;
24                 default:
25                     list = new List();
26                     break;
27             }
28             var data = JsonHelper.ToJsonString(list);
29             var user = userInfoList.FirstOrDefault(x=>x.UserID== frmId);
30             var cOnid= Context.ConnectionId;
31             if (user != null)
32             {
33                 cOnid= user.ConnectionId;
34             }
35             Clients.Client(conid).initChatHistoryData(data, chatType);
36         }
37         /// 
38         /// 添加历史记录数据
39         /// 
40         /// 
41         /// 
42         /// 0公共聊天,1私聊,2群聊
43         public void AddChatHistory(ChatType chatType = 0,string userName="", string message="", string frmId="",string toId="",string roomId="")
44         {
45             ChatHistory history = new ChatHistory()
46             {
47                 Hid = Guid.NewGuid().ToString().ToUpper(),
48                 ChatType = chatType,
49                 Message = message,
50                 UserName = userName,
51                 frmId = frmId,
52                 toId = toId,
53                 RoomId = roomId
54             };
55             chatHistoryList.Add(history); 

以上就是一些主要核心代码。分享给大家共同学习,共同进步。

使用ASP.NET SignalR实现一个简单的聊天室


推荐阅读
  • 本文介绍了多种Eclipse插件,包括XML Schema Infoset Model (XSD)、Graphical Editing Framework (GEF)、Eclipse Modeling Framework (EMF)等,涵盖了从Web开发到图形界面编辑的多个方面。 ... [详细]
  • 深入解析Android Activity生命周期
    本文详细探讨了Android中Activity的生命周期,通过实例代码和详细的步骤说明,帮助开发者更好地理解和掌握Activity各个阶段的行为。 ... [详细]
  • 深入探讨Web服务器与动态语言的交互机制:CGI、FastCGI与PHP-FPM
    本文详细解析了Web服务器(如Apache、Nginx等)与动态语言(如PHP)之间通过CGI、FastCGI及PHP-FPM进行交互的具体过程,旨在帮助开发者更好地理解这些技术背后的原理。 ... [详细]
  • BeautifulSoup4 是一个功能强大的HTML和XML解析库,它能够帮助开发者轻松地从网页中提取信息。本文将介绍BeautifulSoup4的基本功能、安装方法、与其他解析工具的对比以及简单的使用示例。 ... [详细]
  • SpringBoot新手入门指南
    本文旨在为初次接触SpringBoot的开发者提供一份详细的入门指导,包括如何快速搭建并运行一个简单的SpringBoot应用。通过本文,读者将了解Maven项目的构建、必要的配置文件设置以及基本的应用开发流程。 ... [详细]
  • 本文详细介绍了一种实现PopupWindow全屏显示且能有效隐藏虚拟按键的技术方案,适用于Android开发。此方法经过实际测试,表现良好,兼容性优秀。 ... [详细]
  • 本文介绍了如何使用Maven命令对Spring Boot项目中的子模块进行独立打包,包括依赖树的查看、项目的运行和打包等基本操作。 ... [详细]
  • 深入理解异步多线程编程模型
    现代计算机系统中的CPU通过并行处理提高效率,但所谓的并发处理实际上是一种基于轮询的模拟并行。本文探讨了现代处理器如何通过虚拟化技术实现更高的并发性能,以及在.NET框架中如何有效利用线程和异步编程模式。 ... [详细]
  • 本文探讨了 Boost 库中的 Program Options 组件,这是一个强大的工具,用于解析命令行参数和配置文件。文章介绍了如何正确设置和使用该组件,包括处理复杂选项和负数值的方法。 ... [详细]
  • 本文通过具体示例详细介绍了 Python 中的装饰器和装饰类的使用方法,包括带参数的装饰器和装饰类的应用场景。 ... [详细]
  • HDU1085 捕获本·拉登!
    问题描述众所周知,本·拉登是一位臭名昭著的恐怖分子,他已失踪多年。但最近有报道称,他藏匿在中国杭州!虽然他躲在杭州的一个洞穴中不敢外出,但近年来他因无聊而沉迷于数学问题,并声称如果有人能解出他的题目,他就自首。 ... [详细]
  • 本视频详细介绍了如何利用J2EE、JBPM 3.x/4.3、Flex流程设计器、jQuery以及授权认证机制构建高效的企业普及版贝斯OA及工作流管理系统。 ... [详细]
  • BL550721、特点液晶驱动输出:Common输出4线,Segment输出36线内置显示寄存器364144bit2线串行接口(SCL,SDA)内置震荡电路内置液晶驱动电源电路13 ... [详细]
  • 本文介绍了如何在Windows操作系统中安装FFTW库,并详细说明了使用Visual Studio 2010进行4096点快速傅里叶变换(FFT)的步骤。包括下载预编译文件、生成库文件以及配置环境等关键环节。 ... [详细]
  • javascript——对象的概念——函数 1 (函数对象的属性和方法)
    一、创建函数函数是一种对象:Function类是对象,可以通过Function实例化一个函数,不过最多的还是利用function来创建函数。方式一:利用Function类来实例化函 ... [详细]
author-avatar
kevin_xi
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有