使用ASP.NET SignalR实现一个简单的聊天室-阿里云开发者社区

开发者社区> 杰克.陈> 正文

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

简介: 原文:使用ASP.NET SignalR实现一个简单的聊天室  前言   距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多。青春是短暂的,知识是无限的。要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人。
+关注继续查看
原文:使用ASP.NET SignalR实现一个简单的聊天室

 前言

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

 什么是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<UserInfo> userInfoList = new List<UserInfo>();
 6         protected static SignalRContext DbContext = new SignalRContext();
 7         protected static List<ChatHistory> chatHistoryList = new List<ChatHistory>();
 8         #endregion
 9 
10         #region 连接
11       
12         /// <summary>
13         /// 客户端重连接时
14         /// </summary>
15         /// <returns></returns>
16         public override Task OnConnected()
17         {
18             AddUserGroup();//添加用户组
19             UpdateAllRoomList();//更新房间列表
20 
21             return base.OnConnected();
22         }
23         /// <summary>
24         /// 断线
25         /// </summary>
26         /// <param name="stopCalled"></param>
27         /// <returns></returns>
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         /// <summary>
 4         /// 公共聊天
 5         /// </summary>
 6         /// <param name="message"></param>
 7         /// <param name="name"></param>
 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  /// <summary>
 2         /// 发送私聊消息
 3         /// </summary>
 4         /// <param name="sendName">发送名称</param>
 5         /// <param name="userId">用户id</param>
 6         /// <param name="message">消息</param>
 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  /// <summary>
 2         /// 创建聊天室
 3         /// </summary>
 4         /// <param name="roomName"></param>
 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         /// <summary>
26         ///加入聊天室
27         /// </summary>
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         /// <summary>
53         /// 给指定房间内的所有用户发消息
54         /// </summary>
55         /// <param name="room">房间名</param>
56         /// <param name="message">消息</param>
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         /// <summary>
69         /// 退出房间
70         /// </summary>
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('<div class="js-time text-white text-center"><span>' + nickName + '加入了聊天</span></div>');
4     }
View Code

 

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

 1        // <summary>
 2         /// 获取历史记录
 3         /// </summary>
 4         /// <param name="chatType">消息类型0公共聊天,1好友,2群</param>
 5         /// <param name="toId">接收者id</param>
 6         /// <param name="frmId">发送方id</param>
 7         /// <param name="roomId">房间id</param>
 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<ChatHistory>();
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         /// <summary>
38         /// 添加历史记录数据
39         /// </summary>
40         /// <param name="name"></param>
41         /// <param name="message"></param>
42         /// <param name="chatType">0公共聊天,1私聊,2群聊</param>
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); 

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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
微软称Google Android可以使用.NET,徐汇区网站设计
最近Oracle起诉Google使用Java侵权的事件炒得沸沸扬扬,但微软开源技术中心总监Tom Hanraha说,微软不会禁止Google Android使用.NET 技术。Hanraha说:“像Oracle因Java而起诉Google这样的事情,微软是不会做的。
805 0
使用PowerDesigner生成数据库测试数据
原文http://blog.csdn.net/horace20/article/details/6672081 特别说明:本文产生于个人工作总结,转载请注明原文出处http://blog.csdn.net/horace20 1、环境        PowerDesigner15.2.0.3042-BEAN+ MySQL5.5 + mysql-connector-odbc-5.1.8        以上软件在网上都很容易找到,这里就不再给出相关链接!系统环境为WindowsXP。
1029 0
使用Asp.net MVC 2.0 +.NET 4.0 出现 “从客户端 ... 中检测到有潜在危险的 Request.Form 值”错误的解决办法
我们在用Asp.net 开发 Web Form页面时,通常要提交包含Html内容的数据给后台程序代码处理时,会为页面设置 ValidateRequest="false" 属性,设置后,讨厌的 "从客户端 ... 中检测到有潜在危险的 Request.Form 值”的错误乖乖消失了。
639 0
在 Asp.NET MVC 中使用 SignalR 实现推送功能
原文http://www.cnblogs.com/kesalin/archive/2012/11/09/signalr_push.html 在 Asp.NET MVC 中使用 SignalR 实现推送功能 罗朝辉 ( http://www.cnblogs.com/kesalin/ ) CC许可,转载请注明出处   一,简介 Signal 是微软支持的一个运行在 Dot NET 平台上的 html websocket 框架。
1424 0
Asp.net MVC 使用Autofac的简单使用 IOC
Ioc(Inversion of Control)或者叫依赖注入DI(Dependency Injection) 如果一个接口有两个实现类,但是在实现过程中,用到了这两个具体的实现类。 如果采用IOC,则只能是注册一个接口类型,那么如何确保IOC在合适的时候传入不同类的实例?这是我突然间想到的一个问题,希望园友们可以帮忙解答一下!     所谓IOC(控制反转)或者说是依赖注入,就是将你设计好的类交给系统去控制,而不是在你的类内部控制,控制权发生了变化,就称为控制反转。
913 0
使用W“.NET技术”CF实现SOA面向服务编程——简单的WCF开发实例
  前面为大家介绍过WCF的特点,现在再讲解一下WCF基础概念。   在WCF里,各个Application之间的通信是由EndPoint来实现的,EndPoint是WCF实现通信的核心要素。一个WCF Service可由多个EndPoint集合组成,每个EndPoint只能有一种绑定,就是说EndPoint就是通信的入口,客户端和服务端通过 EndPoint交换信息。
690 0
+关注
杰克.陈
一个安静的程序猿~
10427
文章
2
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载