SignalR是什么?
按照官方的说法,signal能够方便的为应用提供实时的服务器端和客户端双向通信功能,相当于服务器端能够观察到客户端的实时更新,并且将这个更新广播推送,这是一个很有用的功能。SignalR适用场景如下
- 需要从服务器进行高频率更新的应用。 示例包括游戏、社交网络、投票、拍卖、地图和 GPS 应用。
- 仪表板和监视应用。 示例包括公司仪表板、即时销售更新或旅行警报。
- 协作应用。 协作应用的示例包括白板应用和团队会议软件。
- 需要通知的应用。 社交网络、电子邮件、聊天、游戏、旅行警报和很多其他应用都需使用通知。
如何使用SignalR?
主要从客户端与服务器端来分解使用的流程:
对于客户端(基于TypeScript):需要创建SignalR的连接服务
import "./css/main.css";
import * as signalR from "@microsoft/signalr";
const divMessages: HTMLDivElement = document.querySelector("#divMessages");
const tbMessage: HTMLInputElement = document.querySelector("#tbMessage");
const btnSend: HTMLButtonElement = document.querySelector("#btnSend");
const username = new Date().getTime();
// 创建与服务器端的连接,这个/hub即定位到后台的集线器文件目录
const connection = new signalR.HubConnectionBuilder()
.withUrl("/hub")
.build();
//这里写的一个消息名字为 "messageReceived" 对应于后台的发送消息名称
connection.on("messageReceived", (username: string, message: string) => {
let messages = document.createElement("div");
messages.innerHTML =
`<div class="message-author">${username}</div><div>${message}</div>`;
divMessages.appendChild(messages);
divMessages.scrollTop = divMessages.scrollHeight;
});
//开启连接,有时可以在中间加上then
connection.start().catch(err => document.write(err));
tbMessage.addEventListener("keyup", (e: KeyboardEvent) => {
if (e.key === "Enter") {
send();
}
});
btnSend.addEventListener("click", send);
//定义一个方法,发送消息定位到后台集线器的newMessage方法,并且置空输入框
function send() {
connection.send("newMessage", username, tbMessage.value)
.then(() => tbMessage.value = "");
}
发送消息也可以使用invoke
connection.invoke("方法名",发送的参数)
对于服务器端:需要创建集线器Hub并且在启动项中配置SignalR的服务
首先需要在启动项目中创建SignalR的服务
services.AddSignalR();
然后创建Hub集线器,另外还可以重写OnConnectedAsync和OnDisConnectedAsync方法来展示连接成功和断开连接时发生的动作
using Microsoft.AspNetCore.SignalR;
using System.Threading.Tasks;
namespace SignalRWebPack.Hubs
{
public class ChatHub : Hub
{
//此处对应前台的send方法中映射到newMessage
public async Task NewMessage(long username, string message)
{
await Clients.All.SendAsync("messageReceived", username, message);
//如果只想被人接收,而自己不接收,可以将All换成others
}
}
}
前后台的关系流转可以用下图来表示
简单web聊天室
客户端代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div>
<input type="text" id="userName" placeholder="用户名"/>
<input type="text" id="message" name="message" value="" placeholder="在此输入需要发送的信息" />
<button type="button" id="sendBtn">发送</button>
</div>
<div>
<div>
<h3>聊天信息</h3>
</div>
<div>
<ul id="messageList" style="height:340px"></ul>
</div>
</div>
<script src="lib/aspnet/signalr/dist/browser/signalr.js"></script>
<script type="text/javascript">
//连接
const connection = new signalR.HubConnectionBuilder()
.withUrl("/myChatHub")
.configureLogging(signalR.LogLevel.Information)
.build();
connection.start().catch(err => console.error(err.toString()));
connection.on("SendMessage", (user, message) => {
const encodedMsg = user + "说:" + message;
const li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messageList").appendChild(li);
});
document.getElementById("sendBtn").addEventListener("click", function () {
var user = document.getElementById('userName').value;
var message = document.getElementById('message').value;
connection.invoke("SendMessage", user, message).catch(err => console.error(err.toString()));
});
</script>
</body>
</html>
服务端代码:
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace webchat
{
public class MychatHub:Hub
{
public async Task SendMessage(string userName,string message)
{
await Clients.All.SendAsync("SendMessage", userName, message);
}
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
return base.OnDisconnectedAsync(exception);
}
}
}
在starup.cs文件中添加SignalR服务以及路由
services.AddSignalR();
app.UseSignalR(route =>
{
route.MapHub<MychatHub>("/myChathub");
});
聊天室效果如下
参考博客:
https://www.cnblogs.com/cgzl/p/9515516.html
https://www.cnblogs.com/yaopengfei/category/1202154.html (从websocket谈到signalR)