您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 1浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

MVC SignalR Hub实时聊天实时Web解决方案

寒冰屋 发布时间:2019-04-13 17:16:58 ,浏览量:1

目录

介绍

背景

1. WebSocket

2.服务器发送事件(SSE)

3.永远的Frame

4.轮询

5.长轮询

场景描述

先决条件

使用代码

第1步:创建项目

步骤2:打开PM以安装依赖项文件

第3步:删除旧依赖关系的指令

第4步:安装必要的依赖项文件的说明

第5步:启动类

第6步:根据我们的场景组织数据库

第7步:创建Hub类

步骤8:创建文件夹并将其命名为Hubs然后创建简单类并将其命名为“MyHub.cs”

规则和约定

提示

  • 下载项目 - 4.35 MB

介绍

如今,由于信息量的增加和实时实现数据的必要性,我们需要技术来满足我们在这个问题上的要求。假设股票市场价格在每个时刻都在变化,您认为用户应该每时每刻刷新页面以告知最后价格吗?显然,对于这样的问题,这不是一个合理的解决方案。或者随着产品和服务的增加,我们需要客户服务来帮助用户和买家,最好和更便宜的沟通方式是通过聊天程序进行对话。出于同样的原因,我们不能强迫用户按下按钮来接收我们的上一条消息。

SignalR是一种实时技术,它使用异步库集在客户端和服务器之间建立持久连接。用户无需使用传统方式即可从服务器接收上次更新的数据,如刷新页面或按下按钮。

背景

您需要了解MVC 4.0技术和EntityFramework> 4.0才能更好地完成本文。

另一方面,SignalR使用以下方法建立实时网络:

1. WebSocket

Websocket是一种全双工协议,在内部使用http握手,允许消息流在TCP之上流动。它支持:Google Chrome(> 16)Fire Fox(> 11)IE(> 10)Win IIS(> 8.0)。由于加密消息和全双工,websocket是最好的解决方案,并且首先signalR检查Web服务器和客户端服务器是否支持websocket。

单工通讯

它只是以一种方式传播,当一个点只是广播而另一个点只能听而不发送信息,如电视和广播。

半双工

一个点发送消息,并且在这一瞬间的另一点无法发送消息,并且应该等待,直到第一点完成其传输,然后发送它的消息,它仅仅是一个每次一个通信线路,诸如旧无线设备对讲机和HTTP协议。

全双工

这两个点可以同时发送和接收消息,不需要等到其他点完成其传输,如电话和websocket协议。

全双工

2.服务器发送事件(SSE)

signalr的下一个选择是服务器发送事件,因为服务器和客户端之间的持久性通信。在这种方法中,通信不会断开连接,服务器的最后数据将自动更新并通过HTTP连接传输到客户端。EventSource是HTML5技术的一部分。

var evsrc = new EventSource("url");
       // Load and Register Event Handler for Messages in this section

       evsrc.addEventListener("message", function (event) {
           //processing data in this section
       });
3.永远的Frame

当客户端向服务器发送请求时,服务器将一个隐藏的iframe作为chunked块发送给客户端,因此这个iframe负责永久保持客户端和服务器之间的连接。每当服务器更改数据,然后将数据作为脚本标记发送到客户端(隐藏的iframe),这些脚本将按顺序接收。

4.轮询

客户端立即向服务器发送请求和服务器响应发送请求,但在那之后,服务器再次断开连接以便在服务器和客户端之间建立通信,我们应该等待来自客户端的下一个请求。要解决此问题,我们必须手动设置超时,并且每10秒客户端向服务器发送请求以检查服务器端的新修改并获取上次更新数据。轮询使用资源,并且它不是经济的解决方案。

5.长轮询

客户端向服务器发送请求,服务器立即响应,此连接一直保持到特定时间,在此期间客户端不必向服务器发送显式请求,而在轮询中客户端必须在超时期间向服务器发送显式请求。Comet编程涵盖了这一概念。

简单的说,SignalR库在客户端和服务器之间选择一种传输数据的类型,其优先级是websocket,服务器发送事件,长轮询和永久iframe。该库中有两个类,如下所示:

1.持续连接

它是低级别的,因此它很复杂,需要更多的配置,但作为回报,它提供了更多的个人处理类的工具。

2. 集线器(Hub)

这是高水平,更受欢迎。

如何借助signalr和hub类实现简单的聊天场景?

我的目的只是发出涉及signalr的随机场景。您可以将它用于您的个人场景,我只需按照以下步骤对服务器(集线器类)和客户端进行挑战,并说明客户端发送请求和服务器如何响应?他们如何互相交流?

场景描述

我想为客户服务部门建立一个应用程序。有些主管部门负责帮助客户,另一方面有客户提出问题并需要帮助。

假设两个管理员在线并连接到聊天服务,第一个客户端来问一个问题,所以系统连接第一个客户端到第一个免费管理员,第二个客户端这个过程会重复,但是第三个客户端从系统发出警报,没有管理员帮忙。每当第一个客户端断开连接时,第一个管理员就会自由。

我对这个场景的约定是使用标志来提醒连接的用户是用户还是管理员,以及哪个用户空闲或忙碌。在我的数据库中,如果admincode等于零,那么它是用户,否则它是管理员,我定义标志“tpflag”(在应用程序中)对于用户等于零,对于管理员等于1。每当他们连接到聊天标志时,“freeflag”变为零,这表示忙碌的用户,并且一旦客户端离开会话,就变成显示空闲状态的会话。

如果 freeflag == 0 ==>忙如果freeflag == 1 ==>空闲如果tpflag == 0 ==>用户如果tpflag == 1 ==> 管理员

先决条件
  1. Visual Studio 2012
  2. SQL Server 2008
  3. 从包管理器控制台安装必要的依赖项
使用代码 第1步:创建项目

文件 - >新项目 - > ASP.Net MVC 4 Web应用程序{提供名称和目录} - > {Template = Basic&View Engine = Razor}

步骤2:打开PM以安装依赖项文件

菜单(工具) - >库包管理器 - >包管理器控制台

第3步:删除旧依赖关系的指令

首先,删除所有旧版本,以便安装新版本的SignalR 2.xx In Line:

PM>Uninstall-Package Microsoft.AspNet.SignalR –RemoveDependencies

第4步:安装必要的依赖项文件的说明

对于新版本,请使用:

PM> Install-Package Microsoft.AspNet.SignalR

我已经使用signalr版本2.0.1进行此练习:

PM> Install-Package Microsoft.AspNet.SignalR -Version 2.0.1

PM>Install-Package Microsoft.Owin

通过编写该指令,nuget可以完成运行signalr所需的所有依赖注入。如果你看一下解决方案中的参考部分,你可以使用Microsoft.ASPNet.SignalR.x,Microsoft.Owin.xx等等,或者如果你看一下解决方案jquery-1.x,jquery.signalR 2.xx等中的Scripts部分,那么对所有依赖感到安慰。

解决方案 - >打开引用 - >

解决方案 - >脚本 - >

另一方面,在成功安装signalR依赖项之后,您将在程序包控制台上方找到readme.txt的完整帮助。它包含了开始使用signalr的所有必要指令。我将在接下来的步骤中解释这些说明。

提示(1):NuGet

如果您遇到此错误“无法解析远程名称:'www.nuget.org'”那么您应该更改位于Package Source前面的Package Manager Settings。

您应该将源从https更改为http协议以解决此问题。

提示(2):Owin

检查您的引用部分以确保有Owin,否则按照以下指示:右键单击引用 - >管理NuGet程序包 - >在左侧选择在线 - >搜索Owin - >选择Owin(Owin IAppBuilder启动界面) - >安装。

然后你应该在你的引用部分看到Owin。

第5步:启动类

要在项目中启用signalr ,您应该将类​​创建为启动类(startup)。(如果在以前版本的signalr中,我的意思是第一个版本,你曾经在global.asax中的Application Start中编写RouteTable.Routes.MapHubs();,现在忘记它并只使用启动类(startup)。右键单击:在项目名称上{SignalR} - >添加类 - - >名称:Startup.cs

using Microsoft.Owin;
using Owin;

[assembly: OwinStartup(typeof(MvcSignal.Startup))]
namespace MvcSignal
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}
第6步:根据我们的场景组织数据库

步骤6.1:创建“tbl_User”

“tbl_user”将收集用户和管理员,如果“AdminCode”由前一个表中的数字填充,那么它是属于department其他人的管理员,如果它被(零)填充说明给普通用户。{“UserID” int + identity=yes and “AdminCode” default value = 0 }

步骤6.2:创建“tbl_Conversation”

“tbl_Conversation”将从用户和管理员之间的对话中收集数据。完成对话后将填写此表格。{“ConID”int + identity = yes}

第7步:创建Hub类

步骤7.1:Model (文件夹) - >创建类“UserInfo.cs”

public class UserInfo
    {
        public string ConnectionId { get; set; }
        public string UserName { get; set; }
        public string UserGroup { get; set; }

        //if freeflag==0 ==> Busy
        //if freeflag==1 ==> Free
        public string freeflag { get; set; }

        //if tpflag==2 ==> User Admin
        //if tpflag==0 ==> User Member
        //if tpflag==1 ==> Admin

        public string tpflag { get; set; }

        public int UserID { get; set; }
        public int AdminID { get; set; } 
    }

步骤7.2:Model (文件夹) - >创建类“MessageInfo.cs”

public class MessageInfo
  {
      public string UserName { get; set; }

      public string Message { get; set; }

      public string UserGroup { get; set; }

      public string StartTime { get; set; }

      public string EndTime { get; set; }

      public string MsgDate { get; set; }
  }

步骤7.3:Model (文件夹)?创建“HomeController.cs”

public ActionResult Chat()
   {
       ViewBag.Message = "Your contact page.";

       return View();
   }

右键单击Chat() - >选择添加视图 - >

步骤7.4:创建Chat.cshtml {Client Side}

@{
    ViewBag.Title = "Chat";
}

User Name: Password :
@section scripts { @**@ @* *@ $(function () { //This section will run whenever we call Chat.cshtml page $("#divChat").hide(); $("#divLogin").show(); var objHub = $.connection.myHub; loadClientMethods(objHub); $.connection.hub.start().done(function () { loadEvents(objHub); }); }); function loadEvents(objHub) { $("#btnLogin").click(function () { var name = $("#txtUserName").val(); var pass = $("#txtPassword").val(); if (name.length > 0 && pass.length > 0) { // > ***** Receive Request From Client [ Connect ] ***** public void Connect(string userName, string password) { var id = Context.ConnectionId; string userGroup=""; //Manage Hub Class //if freeflag==0 ==> Busy //if freeflag==1 ==> Free //if tpflag==0 ==> User //if tpflag==1 ==> Admin var ctx = new TestEntities(); var userInfo = (from m in ctx.tbl_User where m.UserName == userName && m.Password == password select new { m.UserID, m.UserName, m.AdminCode }).FirstOrDefault(); try { //You can check if user or admin did not login before by below line which is an if condition //if (UsersList.Count(x => x.ConnectionId == id) == 0) //Here you check if there is no userGroup which is same DepID --> this is User otherwise this is Admin //userGroup = DepID if ((int)userInfo.AdminCode == 0) { //now we encounter ordinary user which needs userGroup and at this step, //system assigns the first of free Admin among UsersList var strg = (from s in UsersList where (s.tpflag == "1") && (s.freeflag == "1") select s).First(); userGroup = strg.UserGroup; //Admin becomes busy so we assign zero to freeflag which is shown admin is busy strg.freeflag = "0"; //now add USER to UsersList UsersList.Add(new UserInfo { ConnectionId = id, UserID = userInfo.UserID, UserName = userName, UserGroup = userGroup, freeflag = "0", tpflag = "0", }); //whether it is Admin or User now both of them has userGroup and I Join this user or admin to specific group Groups.Add(Context.ConnectionId, userGroup); Clients.Caller.onConnected(id, userName, userInfo.UserID, userGroup); } else { //If user has admin code so admin code is same userGroup //now add ADMIN to UsersList UsersList.Add(new UserInfo { ConnectionId = id, AdminID = userInfo.UserID, UserName = userName, UserGroup = userInfo.AdminCode.ToString(), freeflag = "1", tpflag = "1" }); //whether it is Admin or User now both of them has userGroup and I Join this user or admin to specific group Groups.Add(Context.ConnectionId, userInfo.AdminCode.ToString()); Clients.Caller.onConnected(id, userName, userInfo.UserID, userInfo.AdminCode.ToString()); } } catch { string msg = "All Administrators are busy, please be patient and try again"; //***** Return to Client ***** Clients.Caller.NoExistAdmin(); } } //
关注
打赏
1665926880
查看更多评论
0.0478s