SignalR訊息推送(03)
阿新 • • 發佈:2020-11-25
目錄:
- SignalR概念
- 基本使用
- 對點聊天
1.SignalR
是微軟為實現實時通訊而開發的一個類庫。可進行分散式實時通訊,遠端代理實現。
1.1兩大內部物件
- Persisten Connection
用於客戶端和伺服器端的持久連線。
- Hub(集線器)物件
用於資訊互動,將伺服器端的資料推送(push)至客戶端。
原理:客端建立與服端的連線。客端呼叫服端的方法。服端通過客端傳送的請求,響應資料,呼叫客端的方法將資料推送至客端。
1.2 基本使用
- 建立一個MVC應用程式。
- 在MVC專案的Models資料夾中新增新項 SignalR Hub集線器類。
在建立的Hub類中新增如下程式碼:
//hub別名,方便前臺呼叫
[HubName("getMsg")]
public class MyHub : Hub
{
public void Send(string title,string msg)
{
//呼叫客戶端的sendMessage()方法
Clients.All.sendMessage(title,msg); //其中Clients.All是dynamic型別,sendMessaage()方法是檢視中js定義的function。
}
}
- 在專案中新增 OWIN StartUp 類。
public class Startup
{
public void Configuration(IAppBuilder app)
{
//註冊管道,使用預設的虛擬地址,根目錄下的"/signalr",
//當然你也可以自己定義
app.MapSignalR();
}
}
- 建立控制器和檢視
//建立MessageController,並建立兩個用於顯示檢視的action。
//控制器程式碼:
ublic class MessageController : Controller
{
//傳送訊息
public ActionResult SendMessage()
{
return View();
}
//接收訊息
public ActionResult ReceiveMessage()
{
return View();
}
}
//傳送訊息檢視程式碼:
<h2>傳送訊息</h2>
<div>
標題:<input type="text" id="title" />
</div><br />
<div>
內容:<textarea id="message" rows="4" cols="30"></textarea>
</div>
<br />
<div>
<input type="button" id="sendmessage" value="傳送" />
</div>
<script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
<!--引用自動生成的SignalR 集線器(Hub)指令碼.在執行的時候在瀏覽器的Source下可看到 -->
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自動生成的集線器代理(此處使用別名getMsg)
var chat = $.connection.getMsg;
// 整合器連線開始
$.connection.hub.start().done(function () {
// 服務連線完成,給傳送按鈕註冊單擊事件
$('#sendmessage').click(function () {
// 呼叫伺服器端集線器的Send方法
chat.server.send($("#title").val(), $('#message').val()); //又呼叫了客戶端,客戶端的函式就是新增資訊列,就實現了廣播訊息功能
});
});
});
</script>
//接收訊息檢視程式碼:
<h2>接收訊息</h2>
<div>
<br />
<div id="msgcontent"></div>
</div>
<script src="~/Scripts/jquery.signalR-2.2.2.js"></script>
<script src="~/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
// 引用自動生成的集線器代理
var chat = $.connection.getMsg;
// 定義伺服器端呼叫的客戶端sendMessage來顯示新訊息
chat.client.sendMessage = function (title, message) {
// 向頁面傳送接收的訊息
var html = "<div>標題:" + title + "訊息內容:" + message + "</div>";
$("#msgcontent").after(html);
};
// 整合器連線開始
$.connection.hub.start(); //與SignalR服務建立連線
});
</script>
//<!--引用SignalR庫. -->
<!--引用SignalR庫. -->
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<!--引用自動生成的SignalR 集線器(Hub)指令碼 -->
<script src="~/signalr/hubs"></script>
1.3 實現點對點聊天
Clients物件的所有屬性或方法,具體的定義如下:
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); // 引數中的使用者 }屬性
SignalR會每一個客戶端分配一個ConnnectionId
實現思路:
- 客戶端登入的時候記錄下客戶端的ConnnectionId,並將使用者加入到一個靜態陣列中,該資料為了記錄所有線上使用者。
- 使用者可以點選線上使用者中的使用者聊天,在傳送訊息的時候,需要將ConnectionId一併傳入到服務端。
- 服務端根據傳入的訊息內容和ConnectionId呼叫Clients.Client(connnection).sendMessage方法來進行轉發到對應的客戶端。
[HubName("Chat")] public class ChatHub : Hub { // 靜態屬性,線上使用者列表 public static List<UserInfo> OnlineUsers = new List<UserInfo>(); //登入 public void Login(string userId,string userName) { //獲取客戶端的ConnectionId var connnectId = Context.ConnectionId; OnlineUsers.Add(new UserInfo { ConnectionId = connnectId, UserId = userId, UserName = userName }); // 所有客戶端同步線上使用者 Clients.All.loadUser(OnlineUsers); } /// <summary> /// 傳送私聊 /// </summary> /// <param name="toUserId">接收方使用者連線ID</param> /// <param name="message">內容</param> public void SendPrivateMessage(string toUserId, string message) { var fromUserId = Context.ConnectionId; var toUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == toUserId); var fromUser = OnlineUsers.FirstOrDefault(x => x.ConnectionId == fromUserId); if (toUser != null && fromUser != null) { // 呼叫指定使用者的客戶端方法 Clients.Client(toUserId).receivePrivateMessage(fromUser.UserName, message); } else { //表示對方不線上 Clients.Caller.absentSubscriber(); } } /// <summary> /// 斷線時呼叫 /// </summary> /// <param name="stopCalled"></param> /// <returns></returns> public override Task OnDisconnected(bool stopCalled) { var user = OnlineUsers.FirstOrDefault(u => u.ConnectionId == Context.ConnectionId); // 判斷使用者是否存在,存在則刪除 if (user == null) return base.OnDisconnected(stopCalled); Clients.All.onUserDisconnected(user.ConnectionId, user.UserName); //呼叫客戶端使用者離線通知 // 刪除使用者 OnlineUsers.Remove(user); return base.OnDisconnected(stopCalled); } } //客戶端程式碼: <h2>聊天系統</h2> <div class="container"> @using (Html.BeginForm("login", "Chat", FormMethod.Post, new { @class = "form-inline" })) { <label>使用者Id:</label> @Html.TextBox("userId", "", new { @class = "form-control" }) <label>使用者名稱:</label> @Html.TextBox("userName", "", new { @class = "form-control" }) <input type="button" id="btnLogin" value="登入" class="btn btn-default" /> } </div> <hr /> <div class="container"> <div class="col-md-3"> <div class="panel panel-default"> <div class="panel-heading"> 線上使用者 </div> <div class="panel-body"> <ul id="userList"> </ul> </div> </div> </div> <div class="col-md-8"> <div class="panel panel-default"> <div class="panel-heading"> 聊天內容 </div> <div class="panel-body"> <ul id="msgList" > </ul> </div> <div class="panel-footer"> <label>訊息To:</label> <label id="toUser"></label> @Html.TextBox("msg", "", new { @class = "form-control form-inline" }) <input type="button" id="btnSend" value="傳送" class="btn btn-default" /> </div> </div> </div> </div> @section scripts{ <script src="~/Scripts/jquery.signalR-2.2.2.min.js"></script> <script src="~/signalr/hubs"></script> <script> //使用者點選(選擇使用者) function selectUser(li) { var connectionId = $(li).attr("cid"); $('#toUser').text(connectionId); } $(function () { var chat = $.connection.Chat; //重新整理線上列表 chat.client.loadUser = function (allUsers) { $('#userList').html(""); for (var i = 0; i < allUsers.length; i++) { var li = $('<li cid="' + allUsers[i].ConnectionId+'" onclick="selectUser(this)">' + allUsers[i].UserId + ':' + allUsers[i].UserName + '</li> '); $('#userList').append(li); } } //接收訊息 chat.client.receivePrivateMessage = function (from, msg) { var li = $("<li>來自:" + from + "<br/>" + msg + "</li>"); $("#msgList").append(li); } $.connection.hub.start().done(function () { console.log("連線完成"); //登入 $('#btnLogin').click(function () { chat.server.login($("#userId").val(), $('#userName').val()) }) $('#btnSend').click(function () { chat.server.sendPrivateMessage($('#toUser').text(), $('#msg').val()) }) }); }) </script>實現