Nginx+SignalR+Redis(一)
MVC中SignalR服务端搭建
前言, SignalR即时通讯功能里面有一些前端的类库不是我自己写的,我是大自然的搬运工。我只是改吧改吧
最终效果演示
没个GIF的演示我会拿出来秀?
看上去是不是感觉还可以? 那下面我讲解一下开发步骤。
创建MVC项目
为MVC项目在NuGet中引用SignalR
这里用到了NuGet,网上也有很多资源讲解怎么使用这个。我这里只大概讲解一下。首先打开[工具]-[NuGet 程序包管理器]-[管理解决方案的 NuGet 程序包]
接下来在出现的界面中将程序包源改成:联机,然后搜索SignalR。接下来自行解决~.~
使用SignalR
需要通过Startup类来配置OWIN程序,所以要在项目中加入一个OWIN Startup类
创建好之后配置注入Redis,设置跨域,并开启SignalR其中细节不一一介绍
好了下面,我们再为SignalR创建一个集线器Hubs,我的习惯是在项目中创建一个Hubs目录,然后把需要创建的HubClass放到里面。下面先在项目中创建一个Hubs目录,再在目录上单击右键选择[添加]-[新建项]选择[SignalR 集线器类]
点击确定,再把新建的HubClass中的Hello函数干掉。然后在类上增加一个特性:[HubName("systemHub")]
。既然是要聊天那么自然离不开用户,为了方便管理我建立了一个用户的实体类UserDetail
既然用户类有了,那么我们可以在Hub里面创建一个用户池,用来管理在线用户。
可以将用户池保存至Redis
现在用户池有了,下面需要实现三个功能就能进行登录、上线、下线、私聊操作了。这是下面的逻辑处理代码:
using CacheRedis; using Microsoft.AspNet.SignalR; using Microsoft.AspNet.SignalR.Hubs; using SignalChat.Model; using System; using System.Collections.Generic; using System.Linq; namespace SignalRChat.Hubs { [HubName("systemHub")] public class SystemHub : Hub { /// <summary> /// 登录连线 /// </summary> /// <param name="userID">用户ID</param> /// <param name="userName">用户名</param> /// <param name="deptName">部门名</param> public void Connect(string userID, string userName, string deptName) { var id = Context.ConnectionId; List<UserDetail> ConnectedUsers = RedisCache.Hash_GetAll<UserDetail>(Const.UserPool); if (ConnectedUsers.Count(a => a.ConnectionId == id) == 0) { if (ConnectedUsers.Count(x => x.UserID == userID) > 0) { var items = ConnectedUsers.Where(x => x.UserID == userID).ToList(); foreach (var item in items) { Clients.AllExcept(id).onUserDisconnected(item.ConnectionId, item.UserName); } ConnectedUsers.RemoveAll(x => x.UserID == userID); } //添加在线人员 RedisCache.Hash_Set(Const.UserPool, id, new UserDetail { ConnectionId = id, UserID = userID, UserName = userName, DeptName = deptName, LoginTime = DateTime.Now }); // 反馈信息给登录者 Clients.Caller.onConnected(id, userName, ConnectedUsers); // 通知所有用户,有新用户连接 Clients.AllExcept(id).onNewUserConnected(id, userID, userName, deptName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); } else { //已经连接的用户 } } /// <summary> /// 发送私聊 /// </summary> /// <param name="toUserId">接收方用户连接ID</param> /// <param name="message">内容</param> public void SendPrivateMessage(string toUserId, string message) { string fromUserId = Context.ConnectionId; List<UserDetail> ConnectedUsers = RedisCache.Hash_GetAll<UserDetail>(Const.UserPool); var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId); var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId); if (toUser != null && fromUser != null) { // send to Clients.Client(toUserId).receivePrivateMessage(fromUserId, fromUser.UserName, message); // send to caller user //Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message); } else { //表示对方不在线 Clients.Caller.absentSubscriber(); } } /// <summary> /// 离线 /// </summary> public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) { var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId); if (item != null) { Clients.All.onUserDisconnected(item.ConnectionId, item.UserName); //调用客户端用户离线通知 ConnectedUsers.Remove(item); } return base.OnDisconnected(stopCalled); } } }
我这里写的逻辑只是一个简单的示例,这个可以根据自己的想法和需求任意发挥。至此SignalR服务端已经建立完毕。
下面开始建立SignalR浏览器客户端在解决方案上右键单击添加新建项目,如下图所示
页面视图引入一下js
其中<script src="http://localhost:8080/signalr/hubs"></script>是signalr服务端地址
一下为页面signalr的js介绍
//实例SystemHub,首字母必须小写才能调用 var systemHub = $.connection.systemHub; //开始链接到集线器 $.connection.hub.start().done(function () { //调用服务端函数Connect(首字母小写)以及传递客户端参数进行上线操作 systemHub.server.connect(userid, username, deptname); }); //新用户上线 systemHub.client.onNewUserConnected = function (id, userID, userName, deptName, loginTime) { //定义onNewUserConnected客户端函数供服务端调用 }; //用户离线 systemHub.client.onUserDisconnected = function (id, userName) { //定义onUserDisconnected客户端函数供服务端调用 }; //发送消息时,对方已不在线 systemHub.client.absentSubscriber = function () { //定义absentSubscriber客户端函数供服务端调用 }; //接收消息 systemHub.client.receivePrivateMessage = function (fromUserId, useame, message) { //定义receivePrivateMessage客户端函数供服务端调用 }; //发送消息 systemHub.server.sendPrivateMessage(ChatCore.nowchat.id, data.content);
SignalRChat
作者太难了给作者点辛苦费吧