我们知道传统的http采用的是“拉模型”,也就是每次请求,每次断开这种短请求模式,这种场景下,client是老大,server就像一个小乌龟任人摆布,
很显然,只有一方主动,这事情就没那么完美了,所以为了能够让server也能主动点,html5就应运而生了,或许大家都知道html5中有两种server的主动
模型,第一种叫做websockect,也就是基于tcp模式的双工通讯,还有一种叫做SSE,也就是客户端来订阅服务器的一种事件模型,当然了,在html5出
来之前,如果要做到服务器主动,我们只能采用变相的longpool和foreverframe勉强实现,而signalR这吊毛就是一个对他们进行了高层封装,也就是说
signalR会在这四种技术中根据浏览器和服务器设置采取最优的一种模式,废话不多说,我们快速建立一个例子。

2.快速搭建

1.引入dll

SignalRMvc的简单例子

2.创建hub类(消息处理)

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ServiceStack.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Web;

namespace SignalRMvcDemo
{
    [HubName("MessageHub")]
    public class MessageHub : Hub
    {
        //当前用户
        public static List<UserInfo> OnlineUsers = new List<UserInfo>(); // 在线用户列表
        RedisClient client = new RedisClient("192.168.10.134", 6379, "111111", 3);

        /// <summary>
        /// 登录连线
        /// </summary>
        /// <param name="userId">用户Id</param>
        /// <param name="userName">用户名</param>
        public void Register(string userName)
        {
            OnlineUsers = client.Get<List<UserInfo>>("list") ?? new List<UserInfo>();
            var connnectId = Context.ConnectionId;
            if (!OnlineUsers.Any(x => x.ConnectionId == connnectId))
            {
                //添加在线人员
                OnlineUsers.Add(new UserInfo
                {
                    ConnectionId = connnectId,
                    UserName = userName,
                    LastLoginTime = DateTime.Now
                });
            }
            // 所有客户端同步在线用户
            Clients.All.onConnected(connnectId, userName, OnlineUsers);
            client.Set<List<UserInfo>>("list", OnlineUsers);
        }

        /// <summary>
        /// 发送私聊
        /// </summary>
        /// <param name="toUserId">接收方用户ID</param>
        /// <param name="message">内容</param>
        public void SendPrivateMessage(string toConnectionId, string message)
        {
            OnlineUsers = client.Get<List<UserInfo>>("list") ?? new List<UserInfo>();
            var fromConnectionId = Context.ConnectionId;

            var toUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == toConnectionId);
            var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromConnectionId);

            if (toUser != null)
            {
                Clients.Client(toUser.ConnectionId).receivePrivateMessage(fromUser.ConnectionId, fromUser.UserName, message);
            }
            else
            {
                //表示对方不在线
                Clients.Caller.absentSubscriber();
            }
        }

        /// <summary>
        /// 全部发送
        /// </summary>
        /// <param name="message"></param>
        public void AllSend(string name, string message)
        {
            Clients.All.AllSend(name, message);
        }

        /// <summary>
        /// 连线时调用
        /// </summary>
        /// <returns></returns>
        public override Task OnConnected()
        {
            //Console.WriteLine("客户端连接,连接ID是:{0},当前在线人数为{1}", Context.ConnectionId, OnlineUsers.Count + 1);
            return base.OnConnected();
        }

        /// <summary>
        /// 断线时调用
        /// </summary>
        /// <param name="stopCalled"></param>
        /// <returns></returns>
        public override Task OnDisconnected(bool stopCalled)
        {
            OnlineUsers = client.Get<List<UserInfo>>("list")??new List<UserInfo>();
            var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId);

            // 判断用户是否存在,存在则删除
            if (user == null)
            {
                return base.OnDisconnected(stopCalled);
            }
            // 删除用户
            OnlineUsers.Remove(user);
            Clients.All.onUserDisconnected(OnlineUsers);   //调用客户端用户离线通知
            client.Set<List<UserInfo>>("list", OnlineUsers);

            return base.OnDisconnected(stopCalled);
        }

        /// <summary>
        /// 重新连接时调用
        /// </summary>
        /// <returns></returns>
        public override Task OnReconnected()
        {
            return base.OnReconnected();
        }
    }


    public class UserInfo
    {
        public string ConnectionId { get; set; }
        public string UserName { get; set; }
        public DateTime LastLoginTime { get; set; }
    }
}
View Code

相关文章: