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="width:450px;height:400px;border:1px solid #808080">
      <ul id="messageContext" style="list-style:none">

      </ul>
    </div>
  </div>
  <div style="width: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="width:300px;height:30px;border:1px solid #808080" />
    <input type="button" value="发 送" id="btnSend" />
  </div>
</body>

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

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

最新文章

  1. Codeforces 746D:Green and Black Tea(乱搞)
  2. JSBinding + SharpKit / 实战:转换 Stealth
  3. Incorrect column name &#39;productid &#39;
  4. 错误:error libGL.so: cannot open shared object file: No such file or directory
  5. Javascript执行环境、作用域链
  6. web文档类型DOCTYPE html很重要
  7. 深入解读JavaScript面向对象编程实践
  8. Python基础(十)-模块
  9. python_嵌套列表变成普通列表
  10. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals)A B题
  11. Django扩展自定义manage命令
  12. django模板(一)
  13. Snipaste多截屏工具软件
  14. C语言中使用bool
  15. ionic2中使用datetime组件如何默认设置当前时间?
  16. LeetCode 905 Sort Array By Parity 解题报告
  17. UIDatePicker封装
  18. Android开发之旅(二)服务生命周期和广播接收者生命周期
  19. Log4j2的基本使用
  20. 1 web应用-http协议-web框架

热门文章

  1. lintcode--&gt;翻转字符串
  2. centos6 free 和 centos 7的free 的差异与对比
  3. centos7 Mariadb5.5升级到Mariadb10.2
  4. C和C++结构体的区别
  5. php中接收参数,不论是来自GET还是POST方法
  6. SpringCloud源码解读
  7. Linux下C语言的调试--转
  8. 原生JavaScript 导出excel表格(兼容ie和其他主流浏览器)
  9. PHP初级篇
  10. C# byte 和 char 转化