关键词:
前言
距离我写上一篇博客已经又过了一年半载了,时间过得很快,一眨眼,就把人变得沧桑了许多。青春是短暂的,知识是无限的。要用短暂的青春,去学无穷无尽的知识,及时当勉励,岁月不待人。今天写个随笔小结记录一下。
什么是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
我的项目结构
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
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
一对一聊天方法
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
多对多聊天,群聊方法
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
前端调用后台代码,使用 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 );
后台调用前端的代码。使用 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
最后还有个保存和获取聊天记录的主要方法
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
asp.netsignalr与layim2.0配合轻松实现web聊天室之用redis实现用户在线离线状态消息处理
前言 上一篇中简单讲解了用Redis缓存在线用户逻辑。篇幅也比较小,本篇将详细实现用户的上线下线通知、图片效果转换功能。而且,代码和开发思路都会详细介绍。效果展示 目前有三个用户,user1,user2,user3.下图会简... 查看详情
asp.netsignalr与layim2.0配合轻松实现web聊天室之用redis实现用户在线离线状态消息处理
前言 上篇的预告好像是“聊天室的小细节,你都注意到了吗?”。今天也是为那篇做铺垫吧。之前的版本有好多问题,比如:当前登录用户是否合法问题,userid参数如果随便传后台没有验证。还有一个致命的问题,用... 查看详情
asp.netsignalr与layim2.0配合轻松实现web聊天室(十四)之漏掉的客服消息
前言 不知不觉已经十四篇了,其实已经没有什么可写了。但是突然发现layim中带的客服功能没有用到。于是乎,抽点时间完成吧。其实之前的工作已经把客服功能完成了一大半,剩下的我们稍微调整即可。今天的演示我们放... 查看详情
asp.netsignalr与layim2.0配合轻松实现web聊天室(十三)之附加功能-自定义皮肤
前言 本篇要讲的算是一个layim代码功能扩充。在原来的laim中已经有自带的换肤功能,而且在skin配置中,你可以添加自己想要的皮肤图片路径。这些内容在接下来都不会涉及,本篇要讲的是自定义皮肤功能,没错就是用户自... 查看详情
asp.netsignalr
何为ASP.NETSignalR,有什么用ASP.NETSignalR是一个ASP.NET库,是为了实现实时web通信而创造的,能让服务器与客户端实现即时通信,而不需要服务器等待接收到客户端请求才能返回内容。简言之,就是可以实现服务端主动给客户端发送... 查看详情
signalr2.1简单入门项目
...通讯框架,前台Web页面与后台服务实现数据的交互。ASP.NETSignalR是一个为ASP.NET开发人员的库,简化了将实时web功能添加到应用程序的过程。实时Web功能使服务端代码推送内容到链接可客服端并立即应用成为可能,而不需要服务端... 查看详情
signalr简单封装(代码片段)
...(浏览器)主动发起请求,那么,这个问题怎么解?Asp.NetSignalR是一个Asp.Net 下的类库,可以在Asp.Net 的Web项目中实现实时通信,完美解决这个问题。关于SignalR具体的介绍可以查阅其他资料,或者查看官方文档:http: 查看详情
使用python实现一个简单的智能聊天机器人(代码片段)
简要说明最近两天需要做一个python的小程序,就是实现人与智能机器人(智能对话接口)的对话功能,目前刚刚测试了一下可以实现,就是能够实现个人与机器的智能对话(语音交流)。总体的思路大家可以设想一下,... 查看详情
实现一个的简单的网络聊天程序(代码片段)
...的类和接口,它们提供低层次的通信细节。我们可以直接使用这些类和接口,来专注于网络程序开发,而不用考虑通信的细节。java.ne 查看详情
使用workerman实现在线聊天-第一版
workerman是一个php编写的通讯服务。之前的项目都是用它做数据接口服务这次用它做一个简单的在线聊天室~ 1.下载最新版本的workerman可以去 http://www.workerman.net去下载我这里将service和client分开了两个文件夹,方便管理大致... 查看详情
实现一个简单的视频聊天室(源码)
在《实现一个简单的语音聊天室》一文发布后,很多朋友建议我也实现一个视频聊天室给他们参考一下,其实,视频聊天室与语音聊天室的原理是差不多的,由于加入了摄像头、视频的处理,逻辑会繁杂一些,本文就实现一个简... 查看详情
java中使用udp实现简单的聊天功能
通过DatagramSocket类来实现。此类表示用来发送和接收数据报包的套接字。发送端代码如下:23importjava.io.IOException;4importjava.net.*;5importjava.util.Scanner;67publicclassSendimplementsRunnable{8@Override9publicvoidrun(){10//创建一个发送消息的套接字1 查看详情
求一个c#最简单的tcp传输信息例子(实现聊天和传送文件,再简单点实现聊天也行)
...聊天信息窗口的时候,记得要释放套接字,以便你下次打开使用,否则每个套接字只能使用一次.参考技术A学编程应该有点自己研究的精神,这样的例子在网上数不胜数 参考技术B同求!好心人也给我发份!谢谢了!vrcity2000@yahoo.com.cn... 查看详情
使用java实现一个hello/hi的简单的网络聊天程序(代码片段)
1、socket原理 Socket实质上提供了进程通信的端点。进程通信之前,双方首先必须各自创建一个端点,否则是没有办法建立联系并相互通信的。正如打电话之前,双方必须各自拥有一台电话机一样。 &n... 查看详情
asp.netsignalr系列之源码与总结
1、SignalR1.0与2.0有些不同,以上篇章均只支持2.0+2、必须注意客户端调用服务端对象和方法时的大小写问题3、客户端上的方法不能重名4、IE7及以下的,需要增加json的分析器,分析器下载地址:https://www.nuget.org/packages/json25、以上... 查看详情
使用python实现一个hello/hi的简单的网络聊天程序(代码片段)
一、TCP/IP协议通信原理 TCP/IP协议包含的范围非常的广,它是一种四层协议,包含了各种硬件、软件需求的定义。TCP/IP协议确切的说法应该是TCP/UDP/IP协议。UDP协议(UserDatagramProtocol用户数据报协议),是一种保护消息边界的... 查看详情
实现一个简单的语音聊天室(源码)
...组就是我们用得比较多的。 这篇文章将实现一个简单的语音聊天室,让多个人可以进入同一个房间进行语音沟通。先看运行效果截图: 从左到右的三张图分别是:登录界面、... 查看详情
用go语言实现一个简单的聊天机器人(代码片段)
一、介绍目的:使用Go语言写一个简单的聊天机器人,复习整合Go语言的语法和基础知识。软件环境:Go1.9,Goland2018.1.5。 二、回顾Go语言基本构成要素:标识符、关键字、字面量、分隔符、操作符。它们可以组成各种表达式... 查看详情