使用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 publicView Codevoid Configuration(IAppBuilder app) 7 { 8 app.MapSignalR(); 9 } 10 } 11 }
我的項目結構
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 #endregionView 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 #endregionView 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);
以上就是一些主要核心代碼。分享給大家共同學習,共同進步。
使用ASP.NET SignalR實現一個簡單的聊天室