SignalRの概要と使い方の紹介

零下一度
零下一度オリジナル
2017-06-24 10:45:184133ブラウズ

この章で共有する内容は、Signal R フレームワークを使用して簡単なグループ チャット機能を作成することです。このプロジェクトには公式ドキュメント (もちろんすべて英語) があるため、このフレームワークを .Net の MVC で使用する方法を主に説明します。 , この記事を共有する主な目的は、Web リアルタイム通信を使用する必要がある場合に、より多くのソリューションを友人に提供することです。結局のところ、これは Microsoft が主に推進しているソリューションの 1 つです。

SignalR オンライン紹介

ASP.NET SignalR は、リアルタイム Web 機能をアプリケーションに追加するプロセスを簡素化する、ASP.NET 開発者向けのライブラリです。リアルタイム Web 機能は、クライアントが新しいデータを要求するまでサーバーに待機させるのではなく、サーバー コードが接続されたクライアントが利用可能になるとすぐにコンテンツをプッシュできる機能です。もちろん、SignalR は非常にシンプルで使いやすい高レベル API も提供します。これにより、サーバーはクライアント上で JavaScript 関数を個別またはバッチで呼び出すことができ、次のような接続管理を実行するのに非常に便利です。クライアントのサーバーへの接続または切断 接続、クライアントのグループ化、およびクライアントの承認はすべて、SignalR を使用して非常に簡単に実装できます。

SignalR は、クライアントとのリアルタイム通信を ASP .NET にもたらします。もちろん使いやすく、拡張性も十分です。以前は、ユーザーはデータのリアルタイム表示を実現するためにページを更新するか、Ajax ポーリングを使用する必要がありました。現在では、SignalR を使用するだけで済みます。最も重要なことは、プロジェクトを再作成する必要がなく、既存の ASP .NET プロジェクトを使用して SignalR をシームレスに使用できることです。

グループ チャット インスタンスの効果

まず、テスト ケースの効果を見てみましょう。オンライン効果のリンクは次のとおりです:

Godox Chat Room

(:1001/home/shenniuchat)、レンダリング:

インターフェイスは非常にシンプルであり、ここではスタイルは考慮されません。ここで使用する機能は次のとおりです。

1. オンラインの人数をカウントする

2.オンラインの人数 (このテスト ケースは webSocket と longPolling (長時間接続) をサポートしています)

3. グループ チャット情報

MVC で SignalR を使用する方法

まず、通常どおり MVC Web プロジェクトを作成し、次に Nuget を使用しますコンソール コマンド:

Install-package Microsoft.AspNet。SignalR の依存関係を追加します。自動的に追加されるパッケージは次のとおりです:

  <package id="Microsoft.AspNet.SignalR" version="2.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.JS" version="2.2.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.SignalR.SystemWeb" version="2.2.2" targetFramework="net45" />

、関連する js ファイルを MVC プロジェクトの Script フォルダーに自動的に追加します。次に、Startup.cs というファイル名を持つプロジェクト レベルのディレクトリを作成する必要があります。このクラスの主な内容は完成できません:
jquery.signalR-2.2.2.min.js
jquery.signalR-2.2.2.js

まず、注意すべき点を上から下まで分析します:
1.

OwinStartup(Type)

このタイプは、このコンストラクター クラスを通じて開始位置をマークする Startup クラスに対応します。私のプロジェクトの名前空間、これは簡単に定義できます。
public

void

Configuration(IAppBuilder app) ここで、プログラムは内部のロジックコードを実行するために最初にこのメソッドを入力します。 ;

4.

app.MapSignalR は拡張された IAppBuilder インターフェイス メソッドであり、さまざまな形式の表現があります。ここでは public

static

IAppBuilder MapSignalR(this IAppBuilder ビルダー、string パス、HubConfiguration 構成) を選択します。 );、ここでは MVC ルーティングに少し似ていますが、ここで注目すべき主な点は、フロントエンド ページで使用する必要がある Path パラメーターです。

バックエンドで必要な構成は実際に完了しています。ここでは、

ビジネス ロジック処理クラスを実行する必要がある特定の操作を示します。新しいクラスを作成し (ここでは ChatHub という名前を付けました)、Hub (SignalR フレームワークによって提供されます) を継承します。内部のロジック コードは次のとおりです:

 1 [assembly: OwinStartup(typeof(Stage.Api.Extend.Startup))] 2 namespace Stage.Api.Extend 3 { 4     public class Startup 5     { 6         public void Configuration(IAppBuilder app) 7         { 8             app.MapSignalR("/chat", new Microsoft.AspNet.SignalR.HubConfiguration 9             {10                 EnableDetailedErrors = true,11                 EnableJavaScriptProxies = true12             });13         }14     }15 }

上面的3个方法分别做了:添加聊天人到List,发送信息到客户端,某个连接失效后通知各个有效的聊天人重新加载信息;这里值得关注的是通过重新 public override System.Threading.Tasks.Task OnDisconnected(bool stopCalled) 方法来实现捕获并移除失效连接(这里是聊天人的信息);整篇测试用例通过Context.ConnectionId来保证连接的唯一性,只要有新的链接请求,那么服务端就会分配一个唯一串给这个链接,当客户端关闭页面或关闭链接这个是有就能在OnDisconnected方法中捕获到这个失效的链接的ConnectionId,这样就达到了移除失效聊天人的要求了;为了代码的方便性,这里创建了一个聊天人信息类:

1  public class MoHubUser2     {3 4         public string Id { get; set; }5         public string NickName { get; set; }6         public string TransportMethod { get; set; }7     }

到这里后台的聊天室代码就完成了就是这么简单;我们再来看试图中如何来写代码,这里我先给出我的html布局代码:

 1 @{ 2     ViewBag.Title = "神牛聊天室 - SignalR"; 3 } 4 <style type="text/css"> 5     .div_left { 6         width: 70%; 7         float: left; 8     } 9 10     .div_right {11         width: 28%;12         float: left;13     }14 15     .ul {16         list-style: none;17         border: 1px solid #ccc;18         height: 500px;19         overflow-y: scroll;20         color: black;21     }22 23         .ul li {24             padding-top: 5px;25             padding-right: 25px;26         }27 28     .ul_user {29         list-style: none;30     }31 32         .ul_user li {33             padding-top: 5px;34         }35 36     .send {37         position: relative;38         background: #eae7e7;39         border-radius: 5px; /* 圆角 */40         padding-top: 4px;41         padding-left: 5px;42         margin-top: 13px;43     }44 45         .send .arrow {46             position: absolute;47             top: -16px;48             font-size: 0;49             border: solid 8px;50             border-color: #fff #fff #eae7e7 #fff;51         }52 </style>53 <h3>@ViewBag.Title 在线人数:<span id="sapnUserTotal">0</span>人</h3>54 <div class="container text-left">55     <div class="div_left">56         <ul class="ul" id="discussion"></ul>57         <textarea rows="5" class="form-control" id="message" maxlength="500" placeholder="开始聊天. . ." style="max-width: 100%"></textarea><br />58         <input type="button" id="sendmessage" value="发 送" class="btn btn-default" />59         <input type="hidden" id="displayname" />60     </div>61     <div class="div_right">62         <ul id="users" class="ul_user"></ul>63     </div>64 </div>65 66 <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script>67 @*<script src="~/chat/hubs"></script>*@

客户端这里写法大致有两种选择,一种直接使用生成的代理来操作,一种不用自动生成的代理采用手动创建代理的方式;为了内容的简洁性,这里只简单讲解下自动生成的代理方式,而更多的是分享手动创建代理链接的方式;

使用生成的代理获取链接

首先,我们需要通过Script标签来引用一下自动生成代理的路径:  ,注意啦这里的路径/chat对应的就是咋们在前面Startup.cs文件中配置 app.MapSignalR("/chat" 路径,而后面/hubs固定的写法(至少目前我还没更多的试验过),只有先应用了这个~/chat/hubs,才能在后面使用生成的代理,先上段代码:

 1  var chat = $.connection.chatHub; 2         chat.client.newUser = function (user) { 3             $("#users").append(' <li><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong></li>'); 4         }; 5  6         chat.client.userList = function (users) { 7             console.log(users); 8             $("#sapnUserTotal").html(users.length); 9             $.each(users, function (i, item) {10                 $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>');11             });12         };13         chat.client.addNewMessageToPage = function (user, message) {14             console.log(user);15             $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><div class="send">' + message + '<div class="arrow"></div></div></li>');16         };17    //connection.hub.start({ transport: ['webSockets', 'longPolling'] }).done(function () {18         //    my.TransportMethod = connection.hub.transport.name;19         //    chat.server.addUser(my);20 21         //    $('#sendmessage').click(function () {22         //        //console.log(chat);23         //        var content = $.trim($('#message').val());24         //        if (content.length <= 0) { $('#message').val('').focus(); return; }25         //        chat.server.sendAll(my, content);26         //        $('#message').val('').focus();27         //    });28         //}).fail(function () {29         //    alert("链接聊天室失败,请重新刷新页面。");30         //});

咋们逐步来解析下代码注意点:

1.  var chat = $.connection.chatHub; 这里的chatHub对应的就是咋们创建的并继承Hub的ChatHub类,由于js变量开头都是小写,所以这里是chatHub,这句活就表示链接到咋们后端了ChatHub类了,然后就可以使用里面的方法啦(这种有点类似于早期的webform中某种ajax请求的写法)

2. 通过chat.client.xxx来接收服务端通知的消息,而这个xxx对应的方法名称和咋们后端的Clients.All.xxx,本章实例对应的是:chat.client.userList = function (users){}对应Clients.All.userList(_Users);这样后端就能直接通知客户端的对应方法了;注意这里我后端Clients.All用的是通知全部客户端的意思,如果您需要通知指定的链接需要用到的是: T Client(string connectionId); 方法

3. chat.client是后端调用客户端,那相对的chat.server就是客户端请求服务端,和上面一样通过chat.server.xxx来指定请求的服务端方法,注意这个时候服务端方法指的是继承类Hub的子类的公共方法(本篇对应的是:chat.server.sendAll(my, content)对应ChatHub.cs文件中的 public void SendAll(MoHubUser user, string message) 函数)

4.  connection.hub.start({ transport: ['webSockets', 'longPolling'] }) 来指定运行的交互协议

以上就是使用生成代理的方式,按照上面的注意点来写应该不是问题;

使用手动创建反向代理来链接

不采用生成的代码的方式,我们只需要修改前端就行了,后台代码不用变或设置不用变动;首先我们把上面说的Script引用自动代理的代码去掉,因为这个时候不需要了,我们还是先上代码:

 1 var my = { NickName: "神牛001", TransportMethod: "" }; 2         var connection = $.hubConnection("/chat/hubs"); 3         var chat = connection.createHubProxy('chatHub'); 4  5         chat.on("userList", function (users) { 6             console.log(users); 7             $("#sapnUserTotal").html(users.length); 8             $("#users").html(""); 9             $.each(users, function (i, item) {10                 $("#users").append(' <li>[' + item.TransportMethod + '] <strong>' + item.NickName + '</strong>(' + item.Id + ')</li>');11             });12         });13 14         chat.on("addNewMessageToPage", function (user, message) {15             console.log(user);16             $("#discussion").append(' <li ><span><strong>' + user.NickName + '[' + user.TransportMethod + ']</strong>:</span><div class="send">' + message + '<div class="arrow"></div></div></li>');17 18             var div = document.getElementById('discussion');19             //div.scrollTop = div.scrollHeight;20             div.scrollTop = 999999;21         });22 23         var nickName = prompt("请输入一个昵称:", my.NickName);24         my.NickName = nickName.length > 0 ? nickName : my.NickName;25         $('#displayname').val(nickName);26         $('#message').focus();27      28 29         connection.start({ transport: ['webSockets', 'longPolling'] }).done(function () {30 31             my.TransportMethod = connection.transport.name;32             //console.log(my.TransportMethod);33             chat.invoke("addUser", my);34 35             $('#sendmessage').click(function () {36                 var content = $.trim($('#message').val());37                 if (content.length <= 0) { $('#message').val('').focus(); return; }38 39                 chat.invoke("sendAll", my, content);40                 $('#message').val('').focus();41             });42         });

以下の点もリストされています:

1. var connection = $.hubConnection("/chat/hubs"); リンクを作成します。ここのパスもバックエンドに対応します app.MapSignalR("/chat" 、パスは同じままです

2. var chat = connection.createHubProxy('chatHub'); 、名前ここ: chatHub はバックエンド ChatHub クラス名に対応します

3. on("xxx", function(){}) 関数を使用して、サーバーがクライアントに通知するイベントをバインドします。xxx は Clients.All.xxx に対応します。 xxx

4. connection.start({ Transport: ['webSockets', 'longPolling'] }) で、許可されるリンク方法を設定し、リンクを開始します

5 。リンクの名前を取得する connection.transport.name は、デフォルトで start が設定されていない場合、webSockets、foreverFrame、serverSentEvents、longPolling

6 のタイプがあります。 invoke を介してマップされる Hub クラスを継承するクラスの public メソッド。ここでのインスタンスは以下に対応します。 chat.invoke("sendAll", my, content)public に対応します void SendAll(MoHubUser user, string message)

最後に書きました

上記の点が満たされていれば、基本的なSignalRは連携して問題なく使用できます 注意点はたくさんありますが、体験談をまとめました。この記事を書いているときに、多くの友人が協力してくれることを願っています。そのとき、友人が私の git オープンソース LovePicture.Web プロジェクトを見ていて、彼らも Netcore を使ってアプリケーションを構築しようとしていると言われています。 NetCore の影響力がますます高まっていることを光栄に思います (笑)。おすすめ、ありがとう!

以上がSignalRの概要と使い方の紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。