1. 程式人生 > >使用ASP.NET SignalR實現一個簡單的聊天室

使用ASP.NET SignalR實現一個簡單的聊天室

spl 記錄 歷史 undefine reat 語句 關鍵字 pda name

 前言

  距離我寫上一篇博客已經又過了一年半載了,時間過得很快,一眨眼,就把人變得滄桑了許多。青春是短暫的,知識是無限的。要用短暫的青春,去學無窮無盡的知識,及時當勉勵,歲月不待人。今天寫個隨筆小結記錄一下。

 什麽是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); 

以上就是一些主要核心代碼。分享給大家共同學習,共同進步。

使用ASP.NET SignalR實現一個簡單的聊天室