zoukankan      html  css  js  c++  java
  • Asp.net MVC + Signalr 实现多人聊天室

    Asp.net SignalR

    简介:

      首先简单介绍一下Signalr ,我也是刚接触,觉得挺好玩的,然后写了一个多人聊天室。

      Asp.net SignalR 是为Asp.net 开发人员提供的一个库,可以简化开发人员将实时Web 功能添加到应用程序的过程。实时Web功能是指这样一种功能:当所有连接的客户端变得可用时服务器可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。SignalR 提供了非常简单易用的高阶API,使用服务器端可以单个或批量调用客户端上的javaScript函数,并且非常方便地进行连接管理,例如客户端连接到服务器端,或断开连接,客户端分组,以及客户端授权,使用SignalR 都非常容易实现。

    作用:

      SignalR 将与客户端进行实时通信带给了ASP .NET。当然这样既好用,而且也有足够的扩展性。以前用户需要刷新页面或使用ajax轮询才能实现的实时显示数据。现在只要使用SignalR,就可以简单实现

    测试结果

    代码实现如下 :

      首先我们创建的类需要继承 Hub 类这个类,这个类在 Microsoft.AspNet.SignalR命名空间下面。当然在使用SignalR前,需要安装SignalR相关的.dll 。右键单机项目名称  ==》 管理 NuGet 程序包 ==》 选择浏览 ==》 输入SignalR  一般就是搜索结果的第一个,选择安装就行。

    安装成功之后 , 引用里面会自动引用相关的SignalR包:

    安装完成之后会弹出一个页面 关于Startup.cs 的,初学者千万不要忽略,尽量去看看

    之后我们要添加一个类 ==》新建项 ==》 右上角搜索start  选择OWIN Startup类   命名为Startup :此类事 .Net Web服务器和.Net Web应用之间定义的一套标准接口

     

    Startup 类

    public void Configuration(IAppBuilder app)
    {
      // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
      app.MapSignalR();
    }

    继承Hub 类 :里面有几个方法需重写:

      OnConnected : 当连接连接到此集线器实例时调用。

      OnDisconnected : 当连接与此集线器实例断开时调用。

      OnReconnected : 当连接重新连接到此集线器实例时调用。

      其他详细可参见:

          https://msdn.microsoft.com/zh-cn/library/microsoft.aspnet.signalr.hub(v=vs.111).aspx

      

    在跟目录项创建一个Hubs文件夹,然后添加 DbGroupsHub 类

    HubName :指定Hub连接的名字

    [HubName("dbChatRoomHub")]
    public class DbGroupsHub : Microsoft.AspNet.SignalR.Hub
    {
      public static ContextDbData DbContext = new ContextDbData();
      public string userId;

      /// <summary>
      /// 重写连接事件
      /// </summary>
      /// <returns></returns>
      public override Task OnConnected()
      {
        // 查询用户
        var user = DbContext.listChatRoom.FirstOrDefault(u => u.RoomId != null);
        userId = HttpContext.Current.Request.QueryString["userid"];
        var roomName = user.RoomName;
        JoinRoom(roomName);
        return base.OnConnected();
      }

      //取得在线人员列表
      public void GetOnlinesUser()
      {
        var user = DbContext.listUsers.Where(u => u.status == 1).ToList();
        List<ToolUserInfo> toolInfo = new List<ToolUserInfo>();
        foreach (var item in user)
        {
          ToolUserInfo info = new Models.ToolUserInfo();
          info.LoginId = item.LoginId.ToString();
          info.roomName = item.Rooms.RoomName;
          toolInfo.Add(info);
        }

        Clients.All.GetOnlinesUser(JsonHelper.ToJsonString(toolInfo.ToList()));
      }


      /// <summary>
      /// 给房间内所有的用户发送消息
      /// </summary>
      /// <param name="room">房间名</param>
      /// <param name="message">信息</param>
      public void SendMessage(string room, string message)
      {
        // 调用房间内所有客户端的sendMessage方法
        int id = Convert.ToInt32(HttpContext.Current.Request.QueryString["userid"].ToString());
        var userName = DbContext.listUsers.ToList().SingleOrDefault(s => s.id == id).LoginId;

        ChatRoomInfo info = new Models.ChatRoomInfo();
        info.AddTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
        info.RoomName = room;
        info.Context = message;
        info.LoginId = userName;
        DbContext.listChatRoomInfo.Add(info);
        DbContext.SaveChanges();
        int thisMessageId = info.Id;

        Clients.Group(room, new string[0]).sendMessage(room, message, userName, id, info.AddTime);
      }


      /// <summary>
      /// 加入聊天室
      /// </summary>
      public void JoinRoom(string roomName)
      {
        // 查询聊天室
        //var room = DbContext.Rooms.Find(p => p.RoomName == roomName);
        var room = DbContext.listChatRoom.FirstOrDefault(s => s.RoomName == roomName);

        // 存在则加入
        if (room == null) return;

        // 查找房间中是否存在此用户
        var isExistUser = DbContext.listChatRoomInfo.FirstOrDefault(s => s.LoginId == userId && s.RoomName == roomName);

        // 不存在则加入
        if (isExistUser == null)
        {
          int id = Convert.ToInt32(HttpContext.Current.Request.QueryString["userid"].ToString());
          var user = DbContext.listUsers.FirstOrDefault(s => s.id == id);
          room.Users.Add(user);

          // 将客户端的连接ID加入到组里面
          Groups.Add(Context.ConnectionId, roomName);

          //调用此连接用户的本地JS(显示房间)
          Clients.Client(Context.ConnectionId).joinRoom(roomName);
        }
      }


      // 重写Hub连接断开的事件
      public override Task OnDisconnected(bool stopCalled)
      {
        // 查询用户
        int id = Convert.ToInt32(HttpContext.Current.Request.QueryString["userid"].ToString());
        var user = DbContext.listUsers.FirstOrDefault(u => u.id == id);

        if (user != null)
        {
          // 删除用户
          DbContext.listUsers.Remove(user);
          // 从房间中移除用户
          RemoveUserFromRoom(user.Rooms.RoomName);
        }
        return base.OnDisconnected(stopCalled);
      }


      /// <summary>
      /// 退出
      /// </summary>
      /// <param name="roomName"></param>
      public void RemoveUserFromRoom(string roomName)
      {
        //查找房间是否存在
        var room = DbContext.listChatRoom.FirstOrDefault(a => a.RoomName == roomName);

        // 查找要删除的用户
        int id = Convert.ToInt32(HttpContext.Current.Request.QueryString["userid"].ToString());
        var user = room.Users.FirstOrDefault(a => a.id == id);

        user.status = 0;
        DbContext.SaveChanges();

        // 移除此用户
        room.Users.Remove(user);
        Groups.Remove(Context.ConnectionId, roomName);

        //提示客户端
        Clients.Client(Context.ConnectionId).removeRoom("退出成功!");
      }
    }

    ChatRoom 类

    public class ChatRoom
    {
      [Key]
      public string RoomId { get; set; }

      // 房间名称
      public string RoomName { get; set; }

      // 用户集合
      public List<Users> Users { get; set; }

      public ChatRoom()
      {
        Users = new List<Users>();
      }
    }

    Users 类

    public class Users
    {
      [Key]
      public int id { get; set; }

      public string LoginId { get; set; }

      public string Pwd { get; set; }

      public int status { get; set; } //0:未在线 1:登录在线

      public SignalrStudy.Models.ChatRoom Rooms { get; set; }

    }

    ChatRoomInfo 类

    public class ChatRoomInfo
    {
      [Key]
      public int Id { get; set; }

      public string LoginId { get; set; }

      public string RoomName { get; set; }

      public string Context { get; set; }
      public string AddTime { get; set; }

    }

    MessageContext 类

    public class MessageContext
    {
      [Key]
      public int id { get; set; }
      public string context { get; set; }
      public string sendId { get; set; }
      public string receiveId { get; set; }
    }

    ToolUserInfo 类

    public class ToolUserInfo
    {
      public string LoginId { get; set; }

      public string roomName { get; set; }

    }

    ContextDbData 类

    public class ContextDbData : DbContext
    {
      public ContextDbData() : base("name=ChatRoomDB")
      { }

      public virtual DbSet<Users> listUsers { get; set; }
      public virtual DbSet<MessageContext> listMessageContext { get; set; }
      public virtual DbSet<ChatRoom> listChatRoom { get; set; }

      public virtual DbSet<ChatRoomInfo> listChatRoomInfo { get; set; }
    }

    走到现在服务器代码基本写好了,现在我们开始前端建立连接。

    首先引入我们需要的js文件

    <script src="~/Scripts/jquery-2.2.2.min.js"></script>
    <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>

    <!--这里要注意,这是虚拟目录,也就是你在OWIN Startup中注册的地址-->
    <script src="/signalr/hubs"></script>

    <script type="text/javascript">
      var chat;
      var userId;

      $(function () {

        userId = GetRequest();

        $.connection.hub.qs = { 'userid': userId.Id }

        //此处为建立连接 dbChatRoomHub 为DbGroupsHub 类的 HubName标识属性
        chat = $.connection.dbChatRoomHub;

        //After Service connection
        $.connection.hub.start().done(function () {
          chat.server.getOnlinesUser();
        });

      //Get Current online users
      chat.client.GetOnlinesUser = function (data) {
        if (data)
        {
          var jsondata = $.parseJSON(data);
          $(".Name").text(jsondata[0].roomName);
          $("#OnLineUser").html(" ");
          for (var i = 0; i < jsondata.length; i++) {
            var html = '<li>' + jsondata[i].LoginId + '</li>';
            $("#OnLineUser").append(html);
          }
        }
      }

      //Receive Message
      chat.client.sendMessage = function (room, message, userName, id, time) {
        if (userId.Id == id) {
          var html = '<li style="list-style:none;float:right;margin-top:15px;"><lable style="margin-right:40px;">' + time + '</lable><lable style="margin-right:20px;">' + userName + '</lable></br><lable style="margin-right:30px;">' + message + '</lable></li></br>';
          $("#messageContext").append(html);
        }
        else {
          var html = '<li style="list-style:none;float:left; margin-left:20px;margin-top:15px;"><lable>' + userName + '</lable><lable style="margin-left:40px;">' + time + '</lable></br>&nbsp;&nbsp;&nbsp;&nbsp;<lable>' + message + '</lable></li></br>';
          $("#messageContext").append(html);
        }
      };

      //Post exit operation
      chat.client.removeRoom = function (data) {
        alert(data);
      };

      //Send Message
      $("#btnSend").click(function () {
        var roomname = $(".Name").text();
        var message = $("#message").val();
        chat.server.sendMessage(roomname, message);
        $("#message").val('');
        $("#message").focus();
      })

      //Sign Out ChatRoom
      $("#signout").click(function () {
        var roomname = $(".Name").text();
        chat.server.removeUserFromRoom(roomname);
      })

      //获取url中的参数
      function GetRequest() {
        var url = location.search; //获取url中"?"符后的字串
        var theRequest = new Object();
        if (url.indexOf("?") != -1) {
          var str = url.substr(1);
          strs = str.split("&");
          for (var i = 0; i < strs.length; i++) {
            theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
          }
        }
        return theRequest;
      }

    });
    </script>

    <body style="margin-left:300px;">
      <input type="hidden" id="hiddenVal" value="" />
      <div>欢迎来到<label class="Name"></label></div>
      <div style="margin-top:40px;">
        <div style="float:left">
          <div id="messageContext" style="450px;height:400px;border:1px solid #808080">
          <ul id="messageContext" style="list-style:none">

          </ul>
        </div>
      </div>
      <div style="190px;height:400px;border:1px solid #808080;float:right;margin-right:800px;">
        在线的用户:
        <ul id="OnLineUser">

        </ul>
      </div>
      <div><input type="button" value="退 出" id="signout"/></div>
      </div>
      <div style="margin-top:15px;">
        <input type="text" id="message" style="300px;height:30px;border:1px solid #808080" />
        <input type="button" value="发 送" id="btnSend" />
      </div>
    </body>

    提示:别忘了web.Config中的连接字符串

    写的不好欢迎提意见,我也是初学者,谢谢......

  • 相关阅读:
    如何在仪表板中播放视频
    根据条件显示表格背景色
    如何个性化设置柱形图(条形图)柱子粗细、圆角和颜色?
    如何设置报表参数的日期区间?
    妙用这3个函数,实现各种你意想不到的条件格式化
    利用组合图对数据按百分比区间进行对比展示的实例
    报表传参跳转到仪表板的实现过程
    Wyn仪表板中的图表,如何针对每个字段设置自定义颜色
    Wyn仪表板中设置完整数据格式的方法
    Wyn门户及仪表板颜色设置方式汇总
  • 原文地址:https://www.cnblogs.com/Struggle-xh/p/7677471.html
Copyright © 2011-2022 走看看