zoukankan      html  css  js  c++  java
  • MVC中使用SignalR打造酷炫实用的即时通讯功能附源码

    前言,现在这世道写篇帖子没个前言真不好意思发出来。本贴的主要内容来自于本人在之前项目中所开发的一个小功能,用于OA中的即时通讯。由于当时走的太急,忘记把代码拿出来。想想这已经是大半年前的事情了,时间过了这么久,在当时最新的SignalR2.0.1到现在已经变成了2.2。昨天晚上特地熬了个夜,重新又把它写出来做了一个小小的Demo。当然我只是大自然的搬运工,这个SignalR即时通讯功能里面有一些前端的类库不是我自己写的。我只是改吧改吧~~在此鸣谢 @贤心,是他的几条库才使得我的这个功能如此酷炫。前言猝!

    最终效果演示

    没个GIF的演示我会拿出来秀?

    看上去是不是感觉还可以? 那下面我讲解一下开发步骤。

    创建MVC项目

    首先我们打开VS2015(当然其它的版本也可以。我只是赶了个时髦,有天心血来潮就给安装了),再依次点击[文件]-[新建]-[项目]后弹出如下界面:

    我们选择ASP.NET Web应用程序,并且将项目名称完善好,选择好项目保存路径。再点击确定:

    这里为了让等会的操作更加简单我直接选择了一个ASP.NET 4.5的 Empty 模板。并把下方的“为以下项目添加文件夹和核心引用”选择MVC。再点击确定:

    好了到这里风云突变狂风大作…一个活生生拥有着MVC核心引用和文件夹的项目已经展现在眼前。下面我们就往项目中加入等会要使用到的SignalR。

    为MVC项目在NuGet中引用SignalR

    这里用到了NuGet,网上也有很多资源讲解怎么使用这个。我这里只大概讲解一下。首先打开[工具]-[NuGet 程序包管理器]-[管理解决方案的 NuGet 程序包]

    接下来在出现的界面中将程序包源改成:联机,然后搜索SignalR。接下来自行解决~.~

    使用SignalR

    由于此时的项目还是一个Empty的项目,需要通过Startup类来配置OWIN程序,所以要在项目中加入一个OWIN Startup类

    创建好之后,再在Configuration函数中加入app.MapSignalR();

    好了下面,我们再为SignalR创建一个集线器Hubs,我的习惯是在项目中创建一个Hubs目录,然后把需要创建的HubClass放到里面。下面先在项目中创建一个Hubs目录,再在目录上单击右键选择[添加]-[新建项]选择[SignalR 集线器类]

    点击确定,再把新建的HubClass中的Hello函数干掉。然后在类上增加一个特性:[HubName("systemHub")]。既然是要聊天那么自然离不开用户,为了方便管理我建立了一个用户的实体类UserDetail

     1   /// <summary>
     2  /// 用户细节
     3  /// </summary>
     4  public class UserDetail
     5  {
     6  /// <summary>
     7  /// 连接ID
     8  /// </summary>
     9  public string ConnectionId { get; set; }
    10  /// <summary>
    11  /// 用户ID
    12  /// </summary>
    13  public string UserID { get; set; }
    14  /// <summary>
    15  /// 用户名
    16  /// </summary>
    17  public string UserName { get; set; }
    18  /// <summary>
    19  /// 用户部门
    20  /// </summary>
    21  public string DeptName { get; set; }
    22  /// <summary>
    23  /// 登录时间
    24  /// </summary>
    25  public DateTime LoginTime { get; set; }
    26  }

    既然用户类有了,那么我们可以在Hub里面创建一个用户池,用来管理在线用户。

    1 public static List ConnectedUsers = new List();

    现在用户池有了,下面需要实现三个功能就能进行登录、上线、下线、私聊操作了。这是下面的逻辑处理代码:

     1 /// <summary>
     2 /// 登录连线
     3 /// </summary>
     4 /// <param name="userID">用户ID</param>
     5 /// <param name="userName">用户名</param>
     6 /// <param name="deptName">部门名</param>
     7 public void Connect(string userID, string userName, string deptName)
     8 {
     9     var id = Context.ConnectionId;
    10 
    11     if (ConnectedUsers.Count(x => x.ConnectionId == id) == 0)
    12     {
    13         if (ConnectedUsers.Count(x => x.UserID == userID) > 0)
    14         {
    15             var items = ConnectedUsers.Where(x => x.UserID == userID).ToList();
    16             foreach (var item in items)
    17             {
    18                 Clients.AllExcept(id).onUserDisconnected(item.ConnectionId, item.UserName);
    19             }
    20             ConnectedUsers.RemoveAll(x => x.UserID == userID);
    21         }
    22         //添加在线人员
    23         ConnectedUsers.Add(new UserDetail { ConnectionId = id, UserID = userID, UserName = userName, DeptName = deptName, LoginTime = DateTime.Now });
    24 
    25         // 反馈信息给登录者
    26         Clients.Caller.onConnected(id, userName, ConnectedUsers);
    27 
    28         // 通知所有用户,有新用户连接
    29         Clients.AllExcept(id).onNewUserConnected(id, userID, userName, deptName, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
    30 
    31     }
    32     else
    33     {
    34 
    35     }
    36 }
    37 
    38 /// <summary>
    39 /// 发送私聊
    40 /// </summary>
    41 /// <param name="toUserId">接收方用户连接ID</param>
    42 /// <param name="message">内容</param>
    43 public void SendPrivateMessage(string toUserId, string message)
    44 {
    45     string fromUserId = Context.ConnectionId;
    46     var toUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == toUserId);
    47     var fromUser = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == fromUserId);
    48 
    49     if (toUser != null && fromUser != null)
    50     {
    51         // send to 
    52         Clients.Client(toUserId).receivePrivateMessage(fromUserId, fromUser.UserName, message);
    53 
    54         // send to caller user
    55         //Clients.Caller.sendPrivateMessage(toUserId, fromUser.UserName, message);
    56     }
    57     else
    58     {
    59         //表示对方不在线
    60         Clients.Caller.absentSubscriber();
    61     }
    62 }
    63 
    64 /// <summary>
    65 /// 离线
    66 /// </summary>
    67 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled)
    68 {
    69         var item = ConnectedUsers.FirstOrDefault(x => x.ConnectionId == Context.ConnectionId);
    70         if (item != null)
    71         {
    72             Clients.All.onUserDisconnected(item.ConnectionId, item.UserName); //调用客户端用户离线通知
    73             ConnectedUsers.Remove(item);
    74         }
    75         return base.OnDisconnected(stopCalled);
    76 }

    我这里写的逻辑只是一个简单的示例,这个可以根据自己的想法和需求任意发挥。发挥时遇到问题也欢迎在留言一起交流。服务端代码完了,下面开始建立客户端代码。

    客户端调用SignalR

    到了这里我们貌似还没有新建页面,访问会报404! 那么我们先在Controllers目录上单击右键选择[添加]-[控制器]在弹出的界面中选择[MVC5控制器]

    名字取成Home。然后把@贤心大神的弹层库等等库引用进来。把JS也引用进来。 在这时也能看到在Scripts目录下面有了几个SignalR的js文件。那么既然我们建好Controller了下面就在HomeController的IndexAction上面单击右键选择[添加视图]在调用的时候需要注意的是要引用SignalR的内容:

    1 <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
    2 <script src="~/signalr/hubs"></script>

    至于调用的方法也是比较简单的啦,下面附上简单的示例。更多详细的处理可以下载我的DEMO源码进行参考。

     1 //实例SystemHub,首字母必须小写才能调用
     2 var systemHub = $.connection.systemHub;
     3 //开始链接到集线器
     4 $.connection.hub.start().done(function () {
     5     //调用服务端函数Connect(首字母小写)以及传递客户端参数进行上线操作
     6     systemHub.server.connect(userid, username, deptname);
     7 });
     8 //新用户上线
     9 systemHub.client.onNewUserConnected = function (id, userID, userName, deptName, loginTime) {
    10     //定义onNewUserConnected客户端函数供服务端调用
    11 };
    12 //用户离线
    13 systemHub.client.onUserDisconnected = function (id, userName) {
    14     //定义onUserDisconnected客户端函数供服务端调用
    15 };
    16 //发送消息时,对方已不在线
    17 systemHub.client.absentSubscriber = function () {
    18     //定义absentSubscriber客户端函数供服务端调用
    19 };
    20 //接收消息
    21 systemHub.client.receivePrivateMessage = function (fromUserId, userName, message) {
    22     //定义receivePrivateMessage客户端函数供服务端调用
    23 };
    24 //发送消息
    25 systemHub.server.sendPrivateMessage(ChatCore.nowchat.id, data.content);

    好了,关于MVC中使用SignalR的介绍也详细描述了,我只是抛砖引玉把自己以前开发的功能进行分享以及自己的温习。具体的源码在下方进行下载,如果觉得内容不错,欢迎留言献花以示鼓励~~

    源码下载:FangsiChat.zip


    本文来自 放肆雷特 | 锋哥的技术博客

  • 相关阅读:
    efibootmgr的使用,删除UEFI主板多余启动项。
    各种压缩解压缩命令。
    tar命令排除某文件目录压缩的方法
    豪迪QQ2013群发器破解版9月7日版
    linux virtualbox 访问 usb
    用PPA安装fcitx和搜狗输入法Linux版
    python按行读取文件,去掉换行符" "
    Git常用命令
    Spring中@Autowired 注解的注入规则
    idea导入mavenJar、mavenWeb项目
  • 原文地址:https://www.cnblogs.com/kovin/p/4792594.html
Copyright © 2011-2022 走看看