以下是用signalR通讯的一个例子,有个问题就是每次刷新网页会重新连接一次客户端,求解决办法:
//服务端
try
{
var builder = WebApplication.CreateBuilder(args);
//跨域服务配置
builder.Services.AddCors(options =>
{
options.AddPolicy("Cors", p =>
{
p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation();
builder.Services.AddSignalR();//添加SignalR服务,需要添加到AddRazor后
builder.Services.AddSingleton<SocketConnectionManage>();
builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Error);
builder.Host.UseNLog();
//builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);
builder.Services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
});
builder.Services.AddControllers().AddNewtonsoftJson(option =>
{
option.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
});
app.Urls.Add("http://*:8080");
app.UseCors("Cors");
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();//身份认证必须在静态文件之后,路由之后
app.UseAuthorization();//身份授权
app.UseResponseCaching();//启用服务器缓存
app.MapHub<MessagePushHub>("/messagePushHub");//启用SignalR服务
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
NLogHelper.Trace("应用程序已运行");
}
catch(Exception exception)
{
NLogHelper.Error("Stopped program because of exception", exception);
throw;
}
finally
{
NLog.LogManager.Shutdown();
}
public class MessagePushHub : Hub
{
private readonly SocketConnectionManage _onlineSocketClient;
public MessagePushHub(SocketConnectionManage onlineSocketClient)
{
this._onlineSocketClient = onlineSocketClient;
}
public async Task onOpen(string userId)
{
string connectionId = Context.ConnectionId;
_onlineSocketClient.AddSocket(userId, connectionId);
Console.WriteLine($"客户端{userId},连接成功");
await Task.CompletedTask;
}
public async Task onMessage(string message)
{
string connectionId = Context.ConnectionId;
string userId = _onlineSocketClient.GetUserIdByConnectionId(connectionId);
Console.WriteLine($"[服务端]=>接收到客户端{userId},发送的数据为:{message}");
await this.Clients.Client(connectionId).SendAsync("ReceivePushMessage", message);
await Task.CompletedTask;
}
/// <summary>
/// 客户端连接成功
/// </summary>
/// <returns></returns>
public override Task OnConnectedAsync()
{
return base.OnConnectedAsync();
}
/// <summary>
/// 客户端断开
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception exception)
{
string connectionId = Context.ConnectionId;
string userId = _onlineSocketClient.GetUserIdByConnectionId(connectionId);
Console.WriteLine($"客户端{userId},断开连接");
_onlineSocketClient.RemoveSocket(userId);
return base.OnDisconnectedAsync(exception);
}
}
public class SocketConnectionManage
{
private static ConcurrentDictionary<string, string> _sockets = new ConcurrentDictionary<string, string>();
public void AddSocket(string userId, string connectionId)
{
_sockets.TryAdd(userId, connectionId);
}
public ConcurrentDictionary<string, string> GetClients()
{
return _sockets;
}
public void RemoveSocket(string userId)
{
if (IsExistsUserId(userId))
{
_sockets.TryRemove(userId, out var value);
}
}
public string GetConnectionIdByUserId(string userId)
{
if (IsExistsUserId(userId))
{
string connectionId = _sockets.FirstOrDefault(t => t.Key == userId).Value;
return connectionId;
}
return string.Empty;
}
public string GetUserIdByConnectionId(string connectionId)
{
if (IsExistsConnectionId(connectionId))
{
string userId = _sockets.FirstOrDefault(t => t.Value == connectionId).Key;
return userId;
}
return string.Empty;
}
public bool IsExistsUserId(string userId)
{
return _sockets.Select(s => s.Key).ToList().Exists(t => t == userId);
}
public bool IsExistsConnectionId(string connectionId)
{
return _sockets.Select(s => s.Value).ToList().Exists(t => t == connectionId);
}
}
//客户端
"use strict";
var connection = new signalR.HubConnectionBuilder()
.withUrl("http://localhost:5000/messagePushHub")
.withAutomaticReconnect()
.build();
//Disable send button until connection is established
document.getElementById("btnLogin").disabled = true;
connection.start().then(function () {
document.getElementById("btnLogin").disabled = false;
}).catch(function (err) {
return console.error(err.toString());
});
connection.onreconnecting(error => {
console.log("断线重连中...");
});
connection.onreconnected(connectionId => {
console.log("重连成功...");
//重新绑定用户连接
var txtUserId = document.getElementById("txtUserId").value;
connection.invoke("onOpen", txtUserId).then(function () {
}).catch(function (err) {
return console.error(err.toString());
});
});
connection.on("ReceivePushMessage", function (msg) {
var encodedMsg = "服务端=>向客户端推送的消息为:"+msg;
var li = document.createElement("li");
li.textContent = encodedMsg;
document.getElementById("messagesList").appendChild(li);
});
document.getElementById("btnLogin").addEventListener("click", function (event) {
var txtUserId = document.getElementById("txtUserId").value;
connection.invoke("onOpen", txtUserId).then(function () {
var li = document.createElement("li");
li.textContent = "连接成功";
document.getElementById("messagesList").appendChild(li);
document.getElementById("btnLogin").disabled = true;
}).catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
document.getElementById("btnSendMessage").addEventListener("click", function (event) {
var messageInput = document.getElementById("messageInput").value;
connection.invoke("onMessage", messageInput).catch(function (err) {
return console.error(err.toString());
});
var li = document.createElement("li");
li.textContent = "客户端=>向服务端发送的消息为:"+messageInput;
document.getElementById("messagesList").appendChild(li);
event.preventDefault();
});