????????后端集成SignalR比較簡單,首先要在解決方案中依賴幾個SignalR的庫,SignalR的庫就是做即時通訊的主要庫,我們建立連接、收發(fā)信息都需要用這個庫來進行。
????????除了這幾個庫以外,還要還有幾個依賴庫要一并依賴進來。
? ? ? ? Owin庫的作用主要是為了在項目StartUp時將SignalR庫的幾個Hub文件注冊起來,Hub文件就相當于是我們接口中的Controller文件。
? ? ? ? 然后在項目下創(chuàng)建一個文件夾Hubs,Hubs下創(chuàng)建文件ChatHub
using Common.Log;
using Microsoft.Ajax.Utilities;
using Microsoft.AspNet.SignalR;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using WebGrease;
using WinexHK.Hubs.ConectionOperate;
namespace WinexHK.Hubs
{
? ? /// <summary>
? ? /// ChatHub
? ? /// </summary>
? ? public class ChatHub : PersistentConnection
? ? {
? ? ? ? private ConnectionManagement summaryTableCon = new ConnectionManagement();
? ? ? ? /// <summary>
? ? ? ? /// 連接成功后調(diào)用
? ? ? ? /// </summary>
? ? ? ? /// <param name="request"></param>
? ? ? ? /// <param name="connectionId"></param>
? ? ? ? /// <returns></returns>
? ? ? ? protected override Task OnConnected(IRequest request, string connectionId)
? ? ? ? {
? ? ? ? ? ? //獲得SignalR的連接id
? ? ? ? ? ? var connid = connectionId;
? ? ? ? ? ? //獲得用戶id
? ? ? ? ? ? var userid = "123321";
? ? ? ? ? ? Console.Write($"【{connid}】:已建立連接!");
? ? ? ? ? ? //判斷一下用戶是不是已經(jīng)鏈接了
? ? ? ? ? ? var checkUserConn = summaryTableCon.IsConn(connid, userid);
? ? ? ? ? ? if (!checkUserConn)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //添加一個新的連接
? ? ? ? ? ? ? ? summaryTableCon.AddConnInfo(new SignalRConn()
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? UserId = userid,
? ? ? ? ? ? ? ? ? ? ConnectionId = connid
? ? ? ? ? ? ? ? });
? ? ? ? ? ? }
? ? ? ? ? ? //更新連接
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? summaryTableCon.UpdateConnInfo(userid, connid);
? ? ? ? ? ? }
? ? ? ? ? ? return Connection.Send(connectionId, $"【用戶:{connectionId}】真正連接成功!");
? ? ? ? ? ? //return base.OnConnected(request, connectionId);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 接收到請求的時候調(diào)用
? ? ? ? /// </summary>
? ? ? ? /// <param name="request"></param>
? ? ? ? /// <param name="connectionId"></param>
? ? ? ? /// <param name="data"></param>
? ? ? ? /// <returns></returns>
? ? ? ? protected override async Task OnReceived(IRequest request, string connectionId, string data)
? ? ? ? {
? ? ? ? ? ? var keys = new Dictionary<string, string>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? { "葡萄酒", "wine" },
? ? ? ? ? ? ? ? { "紅酒", "wine" },
? ? ? ? ? ? ? ? { "白酒", "wine" },
? ? ? ? ? ? ? ? { "霞多麗", "grapery" },
? ? ? ? ? ? ? ? { "雷司令", "grapery" }
? ? ? ? ? ? };
? ? ? ? ? ? var values = new Dictionary<string, string>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? { "wine", "這是一款葡萄酒" },
? ? ? ? ? ? ? ? { "grapery", "這是一串葡萄" }
? ? ? ? ? ? };
? ? ? ? ? ? //獲得用戶id
? ? ? ? ? ? var userid = "123321";
? ? ? ? ? ? await Task.Factory.StartNew(async () =>
? ? ? ? ? ? {
? ? ? ? ? ? ? ? var key = "";
? ? ? ? ? ? ? ? for (int i = 0; i < keys.Keys.Count; i++)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? if (data.Contains(keys.Keys.ToList()[i]))
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? key = keys.Values.ToList()[i];
? ? ? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? var value = "未找到匹配條目";
? ? ? ? ? ? ? ? if (values.ContainsKey(key))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? value = values[key];
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? await Connection.Send(connectionId, value);
? ? ? ? ? ? }, TaskCreationOptions.LongRunning);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 連接中斷的時候調(diào)用
? ? ? ? /// </summary>
? ? ? ? /// <param name="request"></param>
? ? ? ? /// <param name="connectionId"></param>
? ? ? ? /// <param name="stopCalled"></param>
? ? ? ? /// <returns></returns>
? ? ? ? protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
? ? ? ? {
? ? ? ? ? ? Console.Write($"【{connectionId}】:已斷開連接!");
? ? ? ? ? ? //獲得SignalR的連接id
? ? ? ? ? ? var connid = connectionId;
? ? ? ? ? ? //關閉連接
? ? ? ? ? ? summaryTableCon.DelConnInfo(connid);
? ? ? ? ? ? return base.OnDisconnected(request, connectionId, stopCalled);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 連接超時重新連接的時候調(diào)用
? ? ? ? /// </summary>
? ? ? ? /// <param name="request"></param>
? ? ? ? /// <param name="connectionId"></param>
? ? ? ? /// <returns></returns>
? ? ? ? protected override Task OnReconnected(IRequest request, string connectionId)
? ? ? ? {
? ? ? ? ? ? return base.OnReconnected(request, connectionId);
? ? ? ? }
? ? }
}
? ? ? ? 文件里有幾個回調(diào)方法,OnConnected用戶連接時,OnReceived收到信息時、OnDisconnected用戶斷開連接,OnReconnected用戶重連,也可以通過Connection.Send方法給連接用戶發(fā)送消息。
? ? ? ? 下面是Hub里用到的用到的ConnectionManagement的代碼,用來保存并管理用戶的連接狀態(tài)。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WinexHK.Hubs.ConectionOperate
{
? ? /// <summary>
? ? /// 連接管理
? ? /// </summary>
? ? public class ConnectionManagement
? ? {
? ? ? ? /// <summary>
? ? ? ? /// 用戶連接集合
? ? ? ? /// </summary>
? ? ? ? public static List<SignalRConn> SignalRConns { get; set; } = new List<SignalRConn>();
? ? ? ? /// <summary>
? ? ? ? /// 添加連接
? ? ? ? /// </summary>
? ? ? ? /// <param name="conn"></param>
? ? ? ? public void AddConnInfo(SignalRConn conn)
? ? ? ? {
? ? ? ? ? ? SignalRConns.Add(conn);
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 刪除連接
? ? ? ? /// </summary>
? ? ? ? /// <param name="connid"></param>
? ? ? ? public void DelConnInfo(string connid)
? ? ? ? {
? ? ? ? ? ? var signalRConns = SignalRConns.FirstOrDefault(u => u.ConnectionId == connid);
? ? ? ? ? ? if (signalRConns != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? SignalRConns.Remove(signalRConns);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 更新鏈接(老的鏈接不起作用了)
? ? ? ? /// 場景:客戶端重連了,userid沒變,但是connid變了
? ? ? ? /// </summary>
? ? ? ? /// <param name="userId">用戶id</param>
? ? ? ? /// <param name="newConnsId">新的鏈接id</param>
? ? ? ? public void UpdateConnInfo(string userId, string newConnsId)
? ? ? ? {
? ? ? ? ? ? var signalRConns = SignalRConns.FirstOrDefault(u => u.UserId.ToLower() == userId.ToLower());
? ? ? ? ? ? if (signalRConns != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? signalRConns.ConnectionId = newConnsId;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? /// <summary>
? ? ? ? /// 判斷用戶是否已經(jīng)鏈接
? ? ? ? /// </summary>
? ? ? ? /// <param name="connid">連接id</param>
? ? ? ? /// <param name="userid">用戶id</param>
? ? ? ? /// <returns></returns>
? ? ? ? public bool IsConn(string connid, string userid)
? ? ? ? {
? ? ? ? ? ? var userConn = SignalRConns.FirstOrDefault(u => u.ConnectionId.ToLower() == connid.ToLower() && u.UserId.ToLower() == userid.ToLower());
? ? ? ? ? ? return userConn == null ? false : true;
? ? ? ? }
? ? }
}
? ? ? ? 最后是用到的一個類,保存用戶id及連接id
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WinexHK.Hubs.ConectionOperate
{
? ? /// <summary>
? ? /// 連接
? ? /// </summary>
? ? public class SignalRConn
? ? {
? ? ? ? /// <summary>
? ? ? ? /// 系統(tǒng)用戶id
? ? ? ? /// </summary>
? ? ? ? public string UserId { get; set; }
? ? ? ? /// <summary>
? ? ? ? /// SignleR鏈接Id(每次鏈接SignalR都會分配一個id)
? ? ? ? /// </summary>
? ? ? ? public string ConnectionId { get; set; }
? ? }
}
? ? ? ? 這幾個類定義好,基本上后端的代碼就完成了,然后開始做前端部分。前端部分分兩個版本,一個是PC版的網(wǎng)頁,一個是uni-app版的網(wǎng)頁,由于uni-app對于SignalR框架的適配性不好,我們暫時先不開發(fā)微信小程序及app版的SignalR,等后面技術成熟了在進行開發(fā)。
? ? ? ? PC版跟uni-app網(wǎng)頁版比較類似,基本上依賴3個js文件就可以搞定了,頁面自己看著改改。
????????
????????一個是js的庫,版本應該都ok,不挑。一個是signalR的庫,還有一個是做聊天要用的調(diào)用方法的庫。下面是chat_hub.js的代碼
? ? ??
// 連接服務,xxxx里直接填后端的地址即可
var connection = $.connection("http://xxxx/chathub");
// 建立鏈接
connection.start(function () {
? ? //連接成功
? ? console.log("【" + new Date().toLocaleString() + "】連接成功!");
? ? //發(fā)送消息
? ? connection.send("給我一杯葡萄酒吧");
});
// 連接斷開
connection.disconnected(function () {
? ? console.log("【" + new Date().toLocaleString() + "】連接斷開!");
});
// 接收服務器發(fā)來的消息
connection.received(function (data) {
? ? console.log("【" + new Date().toLocaleString() + "】接收服務器發(fā)來的消息:");
? ? console.log(data);
});
? ? ? ? uni-app版跟PC版有些不一樣的,因為uni-app不是實時編譯運行的,所以PC的模式對uni-app并不奏效,配進去后發(fā)現(xiàn)JQuery加載不出來,SignalR的js會報錯。
? ? ? ? 解決辦法有兩步,首先在main.js中就將JQuery直接依賴上,并配進window對象中
? ? ? ? 其次要對SignalR中所有用到JQuery的地方進行修改,所有對$的使用都要從window對象中獲取
好比說這個地方,改之前是上面這樣的,改之后是下面這樣的
????????這么改的原因是因為SignalR的js對于uni-app的項目來說屬于外部文件,你在uni-app項目內(nèi)全局引入的JQuery在外部js中并不生效,但window對象是通用的,所以可以在uni-app項目初始化時把JQuery對象保存在window對象中,使用的時候調(diào)window中的$即可。
????????整個文件改完基本就通了,不通你再來問我。文章來源:http://www.zghlxwxcb.cn/news/detail-854132.html
????????文章來源地址http://www.zghlxwxcb.cn/news/detail-854132.html
到了這里,關于后端C# .net 前端uni-app 集成SignalR做即時通訊的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!