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

 

作者太难了给作者点辛苦费吧

posted on 2019-02-01 22:06  锤子龙  阅读(1488)  评论(0编辑  收藏  举报