>  기사  >  백엔드 개발  >  Asp.net SignalR 빠른 시작

Asp.net SignalR 빠른 시작

高洛峰
高洛峰원래의
2016-12-24 14:27:001575검색

오늘의 주제는 모든 사람이 Asp.net SignalR을 빠르게 시작할 수 있도록 돕는 것입니다. 더 이상 고민하지 말고 오늘 주제의 내용을 본격적으로 들어가 보겠습니다.

2. Asp.net SignalR이란
Asp.net SignalR은 실시간 통신을 구현하기 위해 Microsoft에서 제공하는 클래스 라이브러리입니다. 일반적인 상황에서 SignalR은 JavaScript의 긴 폴링 방법을 사용하여 클라이언트와 서버 통신을 구현합니다. Html5에 WebSocket이 등장하면서 SignalR은 WebSocket 통신도 지원합니다. 또한 SignalR에서 개발한 프로그램은 IIS에서 호스팅되는 것으로 제한될 뿐만 아니라 콘솔, 클라이언트 프로그램 및 Windows 서비스를 포함한 모든 응용 프로그램에서도 호스팅될 수 있습니다. 또한 Mono를 지원하므로 교차 배포가 가능합니다. -Linux 환경의 플랫폼.

SignalR 내부에는 두 가지 유형의 개체가 있습니다.

Http 영구 연결 개체: 장기 연결 기능을 해결하는 데 사용됩니다. 클라이언트는 서버에 적극적으로 데이터를 요청할 수도 있으며, 서버는 너무 많은 세부 정보를 구현할 필요가 없습니다. OnConnected, OnReconnected, OnReceived, OnError 및 OnDisconnect와 같이 PertantConnection에서 제공되는 5가지 이벤트만 처리하면 됩니다.
Hub(허브) 개체: 실시간 정보 교환 기능을 해결하는 데 사용됩니다. 서버는 URL을 사용하여 하나 이상의 Hub를 등록할 수 있으며, 이 Hub에 연결되어 있는 한 모든 사람과 공유할 수 있습니다. 클라이언트와 서버의 정보로 전송되며 서버는 클라이언트의 스크립트를 호출할 수 있습니다.
SignalR은 전체 정보 교환을 캡슐화합니다. 클라이언트와 서버는 JSON을 사용하여 통신합니다. 서버에서 선언된 모든 허브 정보는 JavaScript를 생성하여 클라이언트에 출력합니다. .NET은 프록시를 사용하여 내부적으로 프록시 개체를 생성합니다. JSON을 객체로 변환합니다.

클라이언트와 서버 간의 구체적인 상호 작용은 아래 그림과 같습니다.

Asp.net SignalR

위의 소개에서 SignalR이 탄생했음을 알 수 있습니다. 실시간으로 사용 위치를 결정합니다. 구체적인 적용 시나리오는 다음과 같습니다.

1. 온라인 고객 서비스 시스템, IM 시스템 등 채팅방
주가 실시간 업데이트
3. 서비스
4. 게임 내 캐릭터 위치 실시간 푸시
현재 우리 회사에서는 온라인 고객 서비스 시스템을 개발 중입니다.

3. Asp.net SignalR을 사용하여 웹에서 방송 메시지 구현
두 번째 부분의 소개를 통해 모두가 Asp.net SignalR에 대해 사전 이해했다고 믿습니다. 설명을 위한 예제를 통해 모든 사람이 SignalR의 작동 메커니즘에 대한 이해를 심화할 수 있습니다. 첫 번째 예는 SignalR을 사용하여 웹에서 브로드캐스트 메시지를 구현하는 방법입니다.

Visual Studio 2013을 사용하여 MVC 프로젝트를 만듭니다.
Nuget을 통해 SignalR 패키지를 설치합니다. 참조 항목을 마우스 오른쪽 버튼으로 클릭 - "Nuget 패키지 관리 선택" - 설치할 SignalR 패키지를 찾으려면 나타나는 창에 SignalR을 입력합니다.
SignalR을 성공적으로 설치하면 SignalR 라이브러리의 스크립트가 Scripts 폴더에 추가됩니다. 아래 그림과 같이

Asp.net SignalR

4. 프로젝트에 SignalR 허브(v2)를 추가하고 이름을 ServerHub로 지정합니다.

Asp.net SignalR

 5. 방금 생성한 ServerHub 클래스에 다음 코드를 입력합니다.

using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using System;
 
namespace SignalRQuickStart
{public class ServerHub : Hub
  {
    private static readonly char[] Constant =
    {
      '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
      'w', 'x', 'y', 'z',
      'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
      'W', 'X', 'Y', 'Z'
    };
 
    /// <summary>
    /// 供客户端调用的服务器端代码
    /// </summary>
    /// <param name="message"></param>
    public void Send(string message)
    {
      var name = GenerateRandomName(4);
 
      // 调用所有客户端的sendMessage方法
      Clients.All.sendMessage(name, message);
    }
 
    /// <summary>
    /// 产生随机用户名函数
    /// </summary>
    /// <param name="length">用户名长度</param>
    /// <returns></returns>
    public static string GenerateRandomName(int length)
    {
      var newRandom = new System.Text.StringBuilder(62);
      var rd = new Random();
      for (var i = 0; i < length; i++)
      {
        newRandom.Append(Constant[rd.Next(62)]);
      }
      return newRandom.ToString();
    }
  }
}

 6. Startup 클래스를 생성합니다. MVC 프로젝트 생성을 시작할 때 인증이 변경되지 않으면 이 클래스가 기본적으로 추가됩니다. 이미 있었다면 반복해서 추가할 필요가 없습니다. 다음 코드에 따라 Startup 클래스를 업데이트합니다.

7. 홈 컨트롤러에서 홈 작업 메서드를 생성합니다.

public class HomeController : Controller
  {
    public ActionResult Index()
    {
      return View();
    }
 
    public ActionResult About()
    {
      ViewBag.Message = "Your application description page.";
 
      return View();
    }
 
    public ActionResult Contact()
    {
      ViewBag.Message = "Your contact page.";
 
      return View();
    }
 
    public ActionResult Chat()
    {
      return View();
    }
  }

8. Views 파일의 Home 폴더에 생성합니다. Chat 뷰, 뷰 코드는 다음과 같습니다.

@{
  ViewBag.Title = "聊天窗口";
}
 
<h2>Chat</h2>
 
<div class="container">
  <input type="text" id="message" />
  <input type="button" id="sendmessage" value="Send" />
  <input type="hidden" id="displayname" />
  <ul id="discussion"></ul>
</div>
 
@section scripts
{
  <!--引用SignalR库. -->
  <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
   <!--引用自动生成的SignalR 集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到 -->
  <script src="~/signalr/hubs"></script>
   
  <script>
    $(function () {
      // 引用自动生成的集线器代理
      var chat = $.connection.serverHub;
      // 定义服务器端调用的客户端sendMessage来显示新消息
       
      chat.client.sendMessage = function (name, message) {
        // 向页面添加消息
        $(&#39;#discussion&#39;).append(&#39;<li><strong>&#39; + htmlEncode(name)
          + &#39;</strong>: &#39; + htmlEncode(message) + &#39;</li>&#39;);
      };
       
      // 设置焦点到输入框
      $(&#39;#message&#39;).focus();
      // 开始连接服务器
      $.connection.hub.start().done(function () {
        $(&#39;#sendmessage&#39;).click(function () {
          // 调用服务器端集线器的Send方法
          chat.server.send($(&#39;#message&#39;).val());
          // 清空输入框信息并获取焦点
          $(&#39;#message&#39;).val(&#39;&#39;).focus();
        });
      });
    });
     
    // 为显示的消息进行Html编码
    function htmlEncode(value) {
      var encodedValue = $(&#39;<div />&#39;).text(value).html();
      return encodedValue;
    }
  </script>
  }

 9. App_Start 폴더의 RoutConfig 클래스를 수정하고 Action 메서드를 Chat으로 설정합니다.

public class RouteConfig
  {
    public static void RegisterRoutes(RouteCollection routes)
    {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Chat", id = UrlParameter.Optional }
      );
    }
  }

이제 예제가 완성되었습니다. 다음으로 실행 효과를 살펴보고 SignalR이 어떻게 작동하는지 설명하겠습니다. 방송 메시지를 완성하세요. 실행 결과는 다음과 같습니다.

Asp.net SignalR

실행 결과를 보면 아무 창에나 정보를 입력하고 보내면 모든 클라이언트가 메시지를 받는 것을 알 수 있습니다. QQ에 로그인하자마자 Tencent 광고 메시지가 푸시되는 등 실제 애플리케이션에는 이러한 효과가 많이 있습니다.

실행 결과를 읽은 후 코드를 분석하고 SignalR이 어떻게 작동하는지 분석해 보겠습니다.

  按照B/S模式来看,运行程序的时候,Web页面就与SignalR的服务建立了连接,具体的建立连接的代码就是:$.connection.hub.start()。这句代码的作用就是与SignalR服务建立连接,后面的done函数表明建立连接成功后为发送按钮注册了一个click事件,当客户端输入内容点击发送按钮后,该Click事件将会触发,触发执行的操作为: chat.server.send($('#message').val())。这句代码表示调用服务端的send函数,而服务端的Send韩式又是调用所有客户端的sendMessage函数,而客户端中sendMessage函数就是将信息添加到对应的消息列表中。这样就实现了广播消息的功能了。

  看到这里,有人是否会有疑问,前面的实现都只用到了集线器对象,而没有用到持久连接对象。其实并不是如此,$.connection这句代码就是使用持久连接对象,当然你也可以在重新OnConnected方法来查看监控客户端的连接情况,更新的代码如下所示:

public class ServerHub : Hub
 {
   private static readonly char[] Constant =
   {
     &#39;0&#39;, &#39;1&#39;, &#39;2&#39;, &#39;3&#39;, &#39;4&#39;, &#39;5&#39;, &#39;6&#39;, &#39;7&#39;, &#39;8&#39;, &#39;9&#39;,
     &#39;a&#39;, &#39;b&#39;, &#39;c&#39;, &#39;d&#39;, &#39;e&#39;, &#39;f&#39;, &#39;g&#39;, &#39;h&#39;, &#39;i&#39;, &#39;j&#39;, &#39;k&#39;, &#39;l&#39;, &#39;m&#39;, &#39;n&#39;, &#39;o&#39;, &#39;p&#39;, &#39;q&#39;, &#39;r&#39;, &#39;s&#39;, &#39;t&#39;, &#39;u&#39;, &#39;v&#39;,
     &#39;w&#39;, &#39;x&#39;, &#39;y&#39;, &#39;z&#39;,
     &#39;A&#39;, &#39;B&#39;, &#39;C&#39;, &#39;D&#39;, &#39;E&#39;, &#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;I&#39;, &#39;J&#39;, &#39;K&#39;, &#39;L&#39;, &#39;M&#39;, &#39;N&#39;, &#39;O&#39;, &#39;P&#39;, &#39;Q&#39;, &#39;R&#39;, &#39;S&#39;, &#39;T&#39;, &#39;U&#39;, &#39;V&#39;,
     &#39;W&#39;, &#39;X&#39;, &#39;Y&#39;, &#39;Z&#39;
   };
 
   /// <summary>
   /// 供客户端调用的服务器端代码
   /// </summary>
   /// <param name="message"></param>
   public void Send(string message)
   {
     var name = GenerateRandomName(4);
 
     // 调用所有客户端的sendMessage方法
     Clients.All.sendMessage(name, message);
   }
 
   /// <summary>
   /// 客户端连接的时候调用
   /// </summary>
   /// <returns></returns>
   public override Task OnConnected()
   {
     Trace.WriteLine("客户端连接成功");
     return base.OnConnected();
   }
 
   /// <summary>
   /// 产生随机用户名函数
   /// </summary>
   /// <param name="length">用户名长度</param>
   /// <returns></returns>
   public static string GenerateRandomName(int length)
   {
     var newRandom = new System.Text.StringBuilder(62);
     var rd = new Random();
     for (var i = 0; i < length; i++)
     {
       newRandom.Append(Constant[rd.Next(62)]);
     }
     return newRandom.ToString();
   }
 }

   

  这样在运行页面的时候,将在输出窗口看到“客户端连接成功”字样。运行效果如下图所示:

Asp.net SignalR

  在第二部分介绍的时候说道,在服务端声明的所有Hub信息,都会生成JavaScript输出到客户端,为了验证这一点,可以在Chrome中F12来查看源码就明白了,具体如下图所示:

Asp.net SignalR

 看到上图,你也就明白了为什么Chat.cshtml页面需要引入"signalr/hubs"脚本库了吧。

<!--引用SignalR库. -->
  <script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
   <!--引用自动生成的SignalR 集线器(Hub)脚本.在运行的时候在浏览器的Source下可看到 -->
  <script src="~/signalr/hubs"></script>

   

四、在桌面程序中如何使用Asp.net SignalR
   上面部分介绍了SignalR在Asp.net MVC 中的实现,这部分将通过一个例子来看看SignalR在WPF或WinForm是如何使用的。其实这部分实现和Asp.net MVC中非常相似,主要不同在于,Asp.net MVC中的SignalR服务器寄宿在IIS中,而在WPF中应用,我们把SignalR寄宿在WPF客户端中。

下面让我们看看SignalR服务端的实现。

/// <summary>
    /// 启动SignalR服务,将SignalR服务寄宿在WPF程序中
    /// </summary>
    private void StartServer()
    {
      try
      {
        SignalR = WebApp.Start(ServerUri); // 启动SignalR服务
      }
      catch (TargetInvocationException)
      {
        WriteToConsole("一个服务已经运行在:" + ServerUri);
        // Dispatcher回调来设置UI控件状态
        this.Dispatcher.Invoke(() => ButtonStart.IsEnabled = true);
        return;
      }
 
      this.Dispatcher.Invoke(() => ButtonStop.IsEnabled = true);
      WriteToConsole("服务已经成功启动,地址为:" + ServerUri);
    }
 
public class ChatHub : Hub
  {
    public void Send(string name, string message)
    {
      Clients.All.addMessage(name, message);
    }
 
    public override Task OnConnected()
    {
      //
      Application.Current.Dispatcher.Invoke(() =>
        ((MainWindow)Application.Current.MainWindow).WriteToConsole("客户端连接,连接ID是: " + Context.ConnectionId));
 
      return base.OnConnected();
    }
 
    public override Task OnDisconnected(bool stopCalled)
    {
       Application.Current.Dispatcher.Invoke(() =>
        ((MainWindow)Application.Current.MainWindow).WriteToConsole("客户端断开连接,连接ID是: " + Context.ConnectionId));
 
      return base.OnDisconnected(true);
    }
  }
 
 public class Startup
  {
    public void Configuration(IAppBuilder app)
    {
      // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
      // 允许CORS跨域
      //app.UseCors(CorsOptions.AllowAll);
      app.MapSignalR();
    }
  }

   

  通过上面的代码,我们SignalR服务端的实现就完成了,其实现逻辑与Asp.net MVC的代码类似。

  接下来,让我们看看,WPF客户端是如何连接和与服务器进行通信的。具体客户端的实现如下:

public IHubProxy HubProxy { get; set; }
   const string ServerUri = "http://localhost:8888/signalr";
   public HubConnection Connection { get; set; }
 
   public MainWindow()
   {
     InitializeComponent();
 
     // 窗口启动时开始连接服务
     ConnectAsync();
   }
 
   /// <summary>
   /// 发送消息
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void ButtonSend_Click(object sender, RoutedEventArgs e)
   {
     // 通过代理来调用服务端的Send方法
     // 服务端Send方法再调用客户端的AddMessage方法将消息输出到消息框中
     HubProxy.Invoke("Send", GenerateRandomName(4), TextBoxMessage.Text.Trim());
 
     TextBoxMessage.Text = String.Empty;
     TextBoxMessage.Focus();
   }
 
   private async void ConnectAsync()
   {
     Connection = new HubConnection(ServerUri);
     Connection.Closed += Connection_Closed;
 
     // 创建一个集线器代理对象
     HubProxy = Connection.CreateHubProxy("ChatHub");
 
     // 供服务端调用,将消息输出到消息列表框中
     HubProxy.On<string, string>("AddMessage", (name, message) =>
        this.Dispatcher.Invoke(() =>
         RichTextBoxConsole.AppendText(String.Format("{0}: {1}\r", name, message))
       ));
 
     try
     {
       await Connection.Start();
     }
     catch (HttpRequestException)
     {
       // 连接失败
       return;
     }
 
     // 显示聊天控件
     ChatPanel.Visibility = Visibility.Visible;
     ButtonSend.IsEnabled = true;
     TextBoxMessage.Focus();
     RichTextBoxConsole.AppendText("连上服务:" + ServerUri + "\r");
   }

   

  上面的代码也就是WPF客户端实现的核心代码,主要逻辑为,客户端启动的时候就调用Connection.Start方法与服务器进行连接。然后通过HubProxy代理类来调用集线器中Send方法,而集线器中的Send方法又通过调用客户端的addMessage方法将消息输出到客户端的消息框中进行显示,从而完成消息的推送过程。接下来,让我们看看其运行效果:

Asp.net SignalR

   从上面的运行效果看出,其效果和Asp.net MVC上的效果是一样的。

五、总结
   到这里,本专题的所有内容就结束了,这篇SignalR快速入门也是本人在学习SignalR过程中的一些心得体会,希望可以帮助一些刚接触SignalR的朋友快速入门。本篇主要实现了SignalR的广播消息的功能,可以实现手机端消息推送的功能,接下来一篇将介绍如何使用SignalR实现一对一的聊天。


更多Asp.net SignalR快速入门相关文章请关注PHP中文网!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.