上一篇已經簡單介紹了layim WebUI即時通訊元件和獲取資料的後臺方法。現在要討論的是SingalR的內容,之前都是直接貼程式碼。那麼在貼程式碼之前先分析一下業務模型,順便簡單講一下SingalR裡的部分方法。
進入正題,我們要做,即時通訊,就要考慮收發訊息。我們先看推送訊息的方法,找到 interface IHubConnectionContext<T> 介面定義,Hub檔案裡的Clients就是繼承 IHubConnectionContext 介面,方法定義如下:
public interface IHubConnectionContext<T> { T All { get; } T AllExcept(params string[] excludeConnectionIds); T Client(string connectionId); T Clients(IList<string> connectionIds); T Group(string groupName, params string[] excludeConnectionIds); T Groups(IList<string> groupNames, params string[] excludeConnectionIds); T User(string userId); T Users(IList<string> userIds); }
- All全部連線伺服器的客戶端
- AllExcept 除了某些客戶端
- Client 單獨傳送給某個指定客戶端(connectionId是客戶端連線伺服器後自動生成的,單獨單聊天可以使用這個方法,不過此次我沒有使用)
- Clients 多個指定客戶端
- Group 傳送給組內成員,就像QQ群一樣,所有群內成員都能接收到訊息 單獨聊天我採用此思路
- Groups 傳送給多個組,類似群 群發 多個群內的群成員都能接收到訊息
- User 沒使用研究過(不做介紹)
- Users沒使用研究過(不做介紹)
好,結下了,著重講一下用Group 方法實現1對1聊天思路。其實原理還是組推送,只不過組裡就兩個人,大家都用過QQ聊天,聊天框裡面就是兩個人的對話訊息。同理如果一個群裡面就兩個人的話,是不是也是兩個人的對話訊息。所以,如何保證組內就兩個人呢,我採用id+id的思路。
如圖:假如使用者1使用者2都線上,使用者1和使用者2聊天的話,那麼組ID就為使用者1 ID+使用者2 ID,(需要先將使用者ID排序,例如小的在前,大的在後)思路有了,那麼如果不選擇直接拼接,也可以用其他方式生成兩個使用者間的唯一組ID,總之,組名不相同就可以了。
下面在介紹一下,singalR 的 server 和 client。介紹之前呢,準備工作要做好:
第一步:新增Hub檔案
第二步:簡單在Hub檔案裡寫幾個方法,這裡我自定義了HubName為 csHub,然後在 startup檔案裡配置hub路徑
[HubName("csHub")] public class CustomServiceHub : Hub { public Task Join() { return Clients.All.receiveMessage("某某人加入了"); } public void SendMessage(string msg) { // Clients.Group } }
using Microsoft.AspNet.SignalR; using Microsoft.Owin; using Owin; [assembly: OwinStartupAttribute(typeof(LayIM.Startup))] namespace LayIM { public partial class Startup { public void Configuration(IAppBuilder app) { app.Map("/cs", map => { var hubConfiguration = new HubConfiguration() { EnableJSONP = true }; map.RunSignalR(hubConfiguration); }); } } }
第三步:在頁面中引用相應的js
<script src="../Scripts/jquery-1.10.2.min.js"></script> <script src="../Scripts/jquery.signalR-2.1.2.min.js"></script> <script src="http://localhost:20237/cs/hubs"></script>
注意看/cs/hubs 路徑,這個是自動生成的一個js,在瀏覽器中開啟,找一找程式碼,會發現,裡面有server和client
$.hubConnection.prototype.createHubProxies = function () { var proxies = {}; this.starting(function () { // Register the hub proxies as subscribed // (instance, shouldSubscribe) registerHubProxies(proxies, true); this._registerSubscribedHubs(); }).disconnected(function () { // Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs. // (instance, shouldSubscribe) registerHubProxies(proxies, false); }); proxies['csHub'] = this.createHubProxy('csHub'); //建立hub proxies['csHub'].client = { };//在client中自定義新增方法需要前端實現,一般接收資料的方法定義在client裡面 proxies['csHub'].server = { //server裡面實現了Hub檔案中相對應的呼叫方法,注意:他會自動把首字母大寫的改為小寫。 join: function () { return proxies['csHub'].invoke.apply(proxies['csHub'], $.merge(["Join"], $.makeArray(arguments))); }, sendMessage: function (msg) { return proxies['csHub'].invoke.apply(proxies['csHub'], $.merge(["SendMessage"], $.makeArray(arguments))); } }; return proxies; };
第四步:連線伺服器,看看是否成功,js中連線伺服器的寫法有多種。我這裡常用的就是呼叫start 方法
$.connection.hub.start({ jsonp: true }).done(function () { //連線伺服器 _this.proxy.proxyCS.server.join(); console.log('連線成功'); }).fail(function () { console.log("連線失敗"); });
//這行程式碼是封裝的擷取的部分程式碼,主要為了下面演示連線伺服器效果
receiveCallBack: function (result) {
console.log("你收到了新訊息:" + result);
}
我們繼續看一下頁面執行效果,F12看看都傳送了哪些請求
我們看到有start,connect,poll,send等,檢視一下start方法返回的資料 為 Response:started。連線成功了,再看看呼叫join之後返回的資料:
好了配合上邊的部分程式碼,到此為止,與singalR服務的連線就完成了。我們可以呼叫server的join方法傳送資料,在呼叫client的receiveMessage方法接收資料。我把連線服務端的程式碼稍作封裝了一下,只需要引用js(client.hub.js)然後前端初始化方法如下:
var hubConfig = { serverUrl: 'http://localhost:20237/cs' }; $(function () { csClient.init({serverUrl:hubConfig.serverUrl});//init中傳入serverUrl,裡面會自動呼叫連線伺服器方法 });
最後,看一下client.hub.js程式碼
(function ($) { var csHub = { option: { serverUrl: '',//singalr伺服器url receiveCallBack: function (result) { console.log("你收到了新訊息:" + result);//使用者自定義回撥 } }, proxy: { proxyCS: null,//singalr客戶端代理類 }, messageType: { }, //client client: { init: function () { //客戶端 receiveMessage 方法 _this.proxy.proxyCS.client.receiveMessage = function (result) { _this.option.receiveCallBack(result); }; } }, init: function (option) { $.extend(_this.option, option); _this.server.init();//服務端程式碼初始化 _this.client.init();//客戶端程式碼初始化 }, //server server: { //server初始化 init: function () { this.connect(); _this.proxy.proxyCS.client.clientOnConnectedCallBack = this.connectCallBack; }, //連線伺服器 connect: function () { $.connection.hub.url = _this.option.serverUrl; _this.proxy.proxyCS = $.connection.csHub; $.connection.hub.start({ jsonp: true }).done(function () { //連線伺服器 _this.proxy.proxyCS.server.join(); console.log('連線成功'); }).fail(function () { console.log("連線失敗"); }); }, //連線成功之後回撥 connectCallBack: function (result) { console.log(result); } } }; var _this = csHub; window.csClient = _this; })($);
講來將去還是需要貼一點程式碼上來,可能對於不熟悉singalR的同學來說有點難度,沒關係,下一章進入實戰開發環節,手把手教你用SingalR 把客服聊天室搭建起來。不熟悉singalR的同學可以嘗試做一下小的demo。今天的singalR連線就寫到這裡吧。有問題記得留言哦。