首頁 後端開發 C#.Net教程 Asp.net SignalR快速入門

Asp.net SignalR快速入門

Dec 24, 2016 pm 02:27 PM

今天的專題就是讓大家可以快速的上手Asp.net SignalR。廢話不多說了,以下正式進入今天專題的內容。

二、Asp.net SignalR 是個什麼東東
   Asp.net SignalR是微軟為實現即時通訊的一個類別庫。一般情況下,SignalR會使用JavaScript的長輪詢(long polling)的方式來實作客戶端和伺服器通信,隨著Html5中WebSockets出現,SignalR也支援WebSockets通訊。另外SignalR開發的程式不僅限制於宿主在IIS中,也可以宿主在任何應用程序,包括控制台,客戶端程式和Windows服務等,另外還支援Mono,這意味著它可以實現跨平台部署在Linux環境下。

  SignalR內部有兩類物件:

Http持久連接(Persisten Connection)物件:用來解決長時間連接的功能。也可以由客戶端主動向伺服器要求數據,而伺服器端不需要實作太多細節,只需要處理PersistentConnection 內所提供的五個事件:OnConnected, OnReconnected, OnReceived, OnError 和 OnDisconnect 即可。
Hub(集線器)物件:用來解決即時(realtime)資訊交換的功能,服務端可以利用URL來註冊一個或多個Hub,只要連接到這個Hub,就能與所有的客戶端共享發送到伺服器上的訊息,同時服務端可以呼叫客戶端的腳本。
  SignalR將整個訊息的交換封裝起來,客戶端和伺服器都是使用JSON來溝通的,在服務端聲明的所有Hub訊息,都會產生JavaScript輸出到客戶端,.NET則依賴Proxy來產生代理對象,而Proxy的內部則是將JSON轉換成物件。

  客戶端和服務端的具體交互情況如下圖所示:

Asp.net SignalR

  從上面的介紹可以看出,SignalR既然是為實時而生的,這樣就決定了其使用場所。具體適用情境有以下幾點:

1、聊天室,如線上客服系統,IM系統等
2、股票價格即時更新
3、訊息的推播服務
4、遊戲中人物位置的即時推播
   目前,我所在公司在開發的就是線上客服系統。

三、使用Asp.net SignalR在Web端實現廣播訊息
   透過第二部分的介紹,相信大家對Asp.net SignalR有了一個初步的了解,接下來透過兩個例子來讓大家加深對SignalR運行機制的理解。第一個例子就是在Web端如何使用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. 在Home控制器中建立一個Home Action方法

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 9 . 修改App_Start資料夾內的RoutConfig類,將Action方法預設為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>
  }
登入後複製

   

  到此,我們的例子就實現完成了,接下來我們先來看看運行效果,之後再來解釋SignalR是如何來完成廣播訊息的。運行的運行結果如下。

  從運行結果,你可以發現,在任何一個視窗輸入訊息並發送,所有客戶端將收到該訊息。這樣的效果在實際應用中很多,如QQ,一登入QQ的時候都會推播騰訊廣告訊息。

  看完了運行結果,接下來我們來分析下程式碼,進而來剖析下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

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

char在C語言字符串中的作用是什麼 char在C語言字符串中的作用是什麼 Apr 03, 2025 pm 03:15 PM

在 C 語言中,char 類型在字符串中用於:1. 存儲單個字符;2. 使用數組表示字符串並以 null 終止符結束;3. 通過字符串操作函數進行操作;4. 從鍵盤讀取或輸出字符串。

C語言各種符號的使用方法 C語言各種符號的使用方法 Apr 03, 2025 pm 04:48 PM

C 語言中符號的使用方法涵蓋算術、賦值、條件、邏輯、位運算符等。算術運算符用於基本數學運算,賦值運算符用於賦值和加減乘除賦值,條件運算符用於根據條件執行不同操作,邏輯運算符用於邏輯操作,位運算符用於位級操作,特殊常量用於表示空指針、文件結束標記和非數字值。

char在C語言中如何處理特殊字符 char在C語言中如何處理特殊字符 Apr 03, 2025 pm 03:18 PM

C語言中通過轉義序列處理特殊字符,如:\n表示換行符。 \t表示製表符。使用轉義序列或字符常量表示特殊字符,如char c = '\n'。注意,反斜杠需要轉義兩次。不同平台和編譯器可能有不同的轉義序列,請查閱文檔。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

char與wchar_t在C語言中的區別 char與wchar_t在C語言中的區別 Apr 03, 2025 pm 03:09 PM

在 C 語言中,char 和 wchar_t 的主要區別在於字符編碼:char 使用 ASCII 或擴展 ASCII,wchar_t 使用 Unicode;char 佔用 1-2 個字節,wchar_t 佔用 2-4 個字節;char 適用於英語文本,wchar_t 適用於多語言文本;char 廣泛支持,wchar_t 依賴於編譯器和操作系統是否支持 Unicode;char 的字符範圍受限,wchar_t 的字符範圍更大,並使用專門的函數進行算術運算。

char在C語言中如何進行類型轉換 char在C語言中如何進行類型轉換 Apr 03, 2025 pm 03:21 PM

在 C 語言中,char 類型轉換可以通過:強制類型轉換:使用強制類型轉換符將一種類型的數據直接轉換為另一種類型。自動類型轉換:當一種類型的數據可以容納另一種類型的值時,編譯器自動進行轉換。

char數組在C語言中如何使用 char數組在C語言中如何使用 Apr 03, 2025 pm 03:24 PM

char 數組在 C 語言中存儲字符序列,聲明為 char array_name[size]。訪問元素通過下標運算符,元素以空終止符 '\0' 結尾,用於表示字符串終點。 C 語言提供多種字符串操作函數,如 strlen()、strcpy()、strcat() 和 strcmp()。

char和unsigned char的區別是什麼 char和unsigned char的區別是什麼 Apr 03, 2025 pm 03:36 PM

char 和 unsigned char 是存儲字符數據的兩種數據類型,主要區別在於處理負數和正數的方式:值範圍:char 有符號 (-128 到 127),unsigned char 無符號 (0 到 255)。負數處理:char 可以存儲負數,unsigned char 不能。位模式:char 最高位表示符號,unsigned char 無符號位。算術運算:char 和 unsigned char 作為有符號和無符號類型,其算術運算方式不同。兼容性:char 和 unsigned char

See all articles