1. はじめに
Signal は、Microsoft がサポートする HTML WebSocket フレームワークであり、Dot NET プラットフォーム上で実行されます。この出現の主な目的は、サーバーがメッセージをクライアント ページにアクティブにプッシュ (プッシュ) できるようにすることで、クライアントがメッセージを取得するためにリクエストを再送信したりポーリング テクノロジを使用したりする必要がなくなるようにすることです。
詳細については、公式 Web サイト https://github.com/SignalR/ にアクセスしてください。
2. Asp.net SignalR とは何ですか?
Asp.net SignalR は、リアルタイム通信を実現するための Microsoft のクラス ライブラリです。通常の状況では、SignalR は JavaScript のロング ポーリング メソッドを使用してクライアントとサーバーの通信を実装します。Html5 での WebSocket の出現により、SignalR は WebSocket 通信もサポートします。さらに、SignalR によって開発されたプログラムは、IIS でのホストに限定されず、コンソール、クライアント プログラム、Windows サービスなどのあらゆるアプリケーションでホストすることもできます。つまり、Mono をサポートしており、クロスで展開することができます。 -Linux 上のプラットフォーム。
SignalR 内には 2 種類のオブジェクトがあります:
Http Persistent Connection (永続接続) オブジェクト: 長期接続の機能を解決するために使用されます。クライアントはサーバーにアクティブにデータを要求することもでき、サーバーは PersistentConnection で提供される 5 つのイベント (OnConnected、OnReconnected、OnReceived、OnError、OnDisconnect) を処理するだけで十分です。
ハブ (ハブ) オブジェクト: サーバーは、このハブに接続されている限り、URL を使用してすべてのクライアントと共有できます。情報がサーバーに送信され、サーバーはクライアントのスクリプトを呼び出すことができます。
SignalR は、情報交換全体をカプセル化します。クライアントとサーバーは、JSON を使用して通信します。サーバー上で宣言されたすべてのハブ情報は、プロキシに依存してプロキシ オブジェクトを生成します。オブジェクト。
SignalR はリアルタイムで使用するように設計されているため、これによってその使用法が決まります。具体的に適用できるシナリオは次のとおりです:
オンライン顧客サービス システム、IM システムなどのチャット ルーム
株価のリアルタイム更新
メッセージ プッシュ サービス
ゲーム内のキャラクターの位置のリアルタイム プッシュ
現在、私の会社が開発しているのはオンライン接客システムです。
3. 実装メカニズム
SignalR の実装メカニズムは .NET WCF または Remoting に似ており、どちらもリモート エージェントを使用して実装されます。具体的な用途としては、PersistentConnection と Hubs の 2 つのインターフェイスがあり、PersistentConnection は長期的な Javascript ポーリング (Comet と同様) を実装し、Hub は Javascript を使用してリアルタイムの情報交換を行います。動的ロード 実行方法を入力することで実装されます。 SignalR は、接続と情報交換のプロセス全体を非常に美しくカプセル化します。クライアントとサーバーはすべて JSON を使用してデータを交換します。
ハブ インターフェイスを使用するプロセス全体は次のとおりです。
1. サーバー側で対応するハブ クラスを定義します。
2. クライアント側でハブ クラスに対応するプロキシ クラスを定義します。サーバー側で接続を確立します。
4. 次に、クライアントはサーバー側のメソッドを呼び出すことができます。つまり、サーバー側がリクエストを受信した後、 、特定のクライアントまたはグループのクライアントをターゲットにすることができます。1 つのクライアントまたはすべてのクライアントにメッセージを送信します (ブロードキャスト)。
4. Asp.net SignalR を使用して Web 上にブロードキャスト メッセージを実装する
2 番目のパートの紹介を通じて、Asp.net SignalR についての予備的な理解が得られたと思います。次に、2 つの例を使用して深めます。 SignalR の動作メカニズムを理解していること。最初の例は、SignalR を使用して Web 上にブロードキャスト メッセージを実装する方法です。
Nuget を通じて SignalR パッケージをインストールします。参照を右クリックして [Nuget パッケージの管理を選択] 表示されるウィンドウに「SignalR」と入力し、インストールする SignalR パッケージを見つけます。
SignalR が正常にインストールされると、SignalR ライブラリのスクリプトが Scripts フォルダーに追加されます。以下の図に示すように:
SignalR ハブ (v2) をプロジェクトに追加し、ServerHub という名前を付けます。
作成した ServerHub クラスに次のコードを入力します。
using System; using Microsoft.AspNet.SignalR; namespace SignalDemo { 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(); } } }
MVC プロジェクトの作成を開始するときに認証が変更されていない場合、このクラスがデフォルトで追加されます。既に存在する場合は、再度追加する必要はありません。次のコードに従って Startup クラスを更新します。
using Microsoft.Owin; using Owin; [assembly: OwinStartupAttribute(typeof(SignalDemo.Startup))] namespace SignalDemo { public partial class Startup { #region MyRegion public void Configuration(IAppBuilder app) { app.MapSignalR(); ConfigureAuth(app); } #endregion } }
ホーム コントローラーでチャット アクション メソッドを作成します。
using System.Web.Mvc; namespace SignalDemo.Controllers { public class HomeController : Controller { public ActionResult Chat() { return View(); } } }
Views ファイルのホーム フォルダーにチャット ビューを作成します。 ビュー コードは次のとおりです。
修改App_Start文件夹内的RoutConfig类,将Action方法默认设置为Chat
using System.Web.Mvc; using System.Web.Routing; namespace SignalDemo { 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是如何来完成广播消息的。运行的运行结果如下。
从运行结果,你可以发现,在任何一个窗口输入信息并发送,所有客户端将收到该消息。这样的效果在实际应用中很多,如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 = { '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> /// <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(); } }
这样在运行页面的时候,将在输出窗口看到“客户端连接成功”字样。运行效果如下图所示:
在第二部分介绍的时候说道,在服务端声明的所有Hub信息,都会生成JavaScript输出到客户端,为了验证这一点,可以在Chrome中F12来查看源码就明白了,具体如下图所示:
看到上图,你也就明白了为什么Chat.cshtml页面需要引入"signalr/hubs"脚本库了吧。
五、在桌面程序中如何使用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 MVC上的效果是一样的。
总结
到这里,本专题的所有内容就结束了,这篇SignalR快速入门也是本人在学习SignalR过程中的一些心得体会,希望可以帮助一些刚接触SignalR的朋友快速入门。本篇主要实现了SignalR的广播消息的功能,可以实现手机端消息推送的功能,接下来一篇将介绍如何使用SignalR实现一对一的聊天。
SignalR を使用して Asp.NET MVC にプッシュ関数を実装する方法に関するその他の記事については、PHP 中国語 Web サイトに注目してください。