zoukankan      html  css  js  c++  java
  • 使用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); 

    以上就是一些主要核心代码。分享给大家共同学习,共同进步,代码方面欢迎各位大佬指点。
    后期补充:github地址

    ASP.NET SignalR+MVC+BootStrap:https://github.com/wyanmei/SignalRChat

    前后端分离的部分,我做成了两个项目,ASP.NET SignalR+WepApi+BootStrap+Vue.js
    WebApi后端项目地址:https://github.com/wyanmei/SignalRChatForWebApi
    Vue.js前端项目地址:https://github.com/wyanmei/SignalRChatForVue




  • 相关阅读:
    Oracle 11g SQL Fundamentals Training Introduction02
    Chapter 05Reporting Aggregated data Using the Group Functions 01
    Chapter 01Restriicting Data Using The SQL SELECT Statemnt01
    Oracle 11g SQL Fundamentals Training Introduction01
    Chapter 04Using Conversion Functions and Conditional ExpressionsConditional Expressions
    Unix时代的开创者Ken Thompson (zz.is2120.bg57iv3)
    我心目中计算机软件科学最小必读书目 (zz.is2120)
    北京将评估分时分区单双号限行 推进错时上下班 (zz)
    佳能G系列领军相机G1X
    选购单反相机的新建议——心民谈宾得K5(转)
  • 原文地址:https://www.cnblogs.com/wwym/p/8780798.html
Copyright © 2011-2022 走看看