关键词:
【中文标题】如何终止 SignalR 连接?【英文标题】:How can I kill a SignalR connection? 【发布时间】:2020-07-04 03:33:22 【问题描述】:我正在使用 SignalR 在网站上传输数据。但是 SignalR 应该只能在一段时间内发送数据,如果该时间段已过,则应终止连接。
如果请求仍处于挂起状态且未完成,则停止功能 $.connection.hub.stop()
将被取消。但是无论发送了多少数据,这个请求都应该被强制取消。
我如何杀死 SignalR-Connection?
【问题讨论】:
【参考方案1】:正如您在 Microsoft Documentation about Timeout and keepalive settings 中看到的,您可以在选项中定义 DisconnectTimeout。
例子:
protected void Application_Start(object sender, EventArgs e)
// Make long-polling connections wait a maximum of 110 seconds for a
// response. When that time expires, trigger a timeout command and
// make the client reconnect.
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(110);
// Wait a maximum of 30 seconds after a transport connection is lost
// before raising the Disconnected event to terminate the SignalR connection.
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(30);
// For transports other than long polling, send a keepalive packet every
// 10 seconds.
// This value must be no more than 1/3 of the DisconnectTimeout value.
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(10);
RouteTable.Routes.MapHubs();
编辑:由于无论如何您都想终止来自客户端的连接,因此您正在谈论 CancellationToken
行为,但不幸的是,这在 SignalR 中仍然不支持,如您所见 @987654322 @ 和here,团队想对SignalR
这样做,但仍然没有任何消息。
【讨论】:
正如我所说,来自前端站点的请求尚未完成,因此前端仍有一些数据要发送到 SignalR-Backend/Hub。所以我正在寻找一个前端解决方案,因为发送了大量的数据,如果经过一段时间,那么无论数据是否已经传输,前端都应该终止连接。你明白我在找什么吗? @Snickbrack 你想通过客户端终止连接,即使你现在正在发送数据,我是对的? @Snickbrack 不要忘记选择您问题的正确答案,这里或其他答案...【参考方案2】:请阅读this microsoft 关于 Hub 生命周期事件的文档。您可以更改这些设置的默认值,在您的Global.asax
文件中的Application_Start
中设置它们。但是这样你就不能完全控制客户端。因此,您使用 javascript setTimeout
函数并在新用户连接时从服务器端传递时间。它可能是 GlobalHost.Configuration.DisconnectTimeout
或您想要的任何时间。我用演示项目给出了一个完整的例子。实际上我在一个非常大的票务系统中使用这个逻辑来实时持有票。(请阅读所有内联评论)
型号:
public class MyModel
public int Id get; set;
public string Name get; set;
public static string Send(MyModel my)
//Do Somthing
return $"Data Sending to my.Name...";
public static string Stop(string name)
//Do Somthing
return $"ForceStop name.";
public static string Delete()
//Do Somthing
return "Deleted";
中心:
[HubName("myHub")]
public class MyHub : Hub
int connectionTimeOut = 10;//sec
[HubMethodName("connect")]
public void Connect()
//apply logic if any when user connected or reload page
//set connection Time Out as you need
connectionTimeOut= 10;// GlobalHost.Configuration.DisconnectTimeout
Clients.Client(Context.ConnectionId).onNewUserConnected(connectionTimeOut);
[HubMethodName("startSendingServer")]
public void StartSending(int id, string name)//pass anything you need
//apply logic if any when start sending data
var my = new MyModel
Id = id,
Name = name
;
var status = MyModel.Send(my);//example
var result = new
status,
name
;
Clients.Client(Context.ConnectionId).startSendingClient(result);
[HubMethodName("forceStopServer")]
public void ForceStop(string name)//pass anything you need
//apply logic if any when force stop sending data
var status = MyModel.Stop(name);
Clients.Client(Context.ConnectionId).forceStopClint(status);
public override Task OnDisconnected(bool stopCalled)
//apply logic if any when connection Disconnected
var status = MyModel.Delete();//example
if (stopCalled)
// status=String.Format("Client 0 explicitly closed the connection.", Context.ConnectionId)
//your code here
else
// status=String.Format("Client 0 timed out .", Context.ConnectionId);
//your code here
//Clients.Client(Context.ConnectionId).onUserDisconnected(status);
return base.OnDisconnected(stopCalled);
测试视图:
<div class="row">
<div class="col-md-12">
<h1> Status: <span id="hubStatus"></span></h1>
<br />
<h4> Countdown : <span id="counter"></span></h4>
<br />
<button id="btnHub" class="btn btn-primary btn-lg">Start Sending Data</button>
</div>
</div>
@section scripts
<script src="~/Scripts/app/hub.js"></script>
hub.js:
var proxyTimer = null;
var sendTimeLimit = 1;//sec
var sessionTime = sendTimeLimit * 1000;
$(function ()
var myProxy = $.connection.myHub;
$.connection.hub.start().done(function ()
registerServerEvents(myProxy);
);
clientMethods(myProxy);
);
function registerServerEvents(proxyHub)
proxyHub.server.connect();
$(document).on("click", "#btnHub", function (e)
$("#hubStatus").html("Sending..");
$("#btnHub").text("Count Down Start...");
//Logic Before start sending data.
var id = 1;
var name = "AzR";
proxyHub.server.startSendingServer(id,name);
// $.connection.hub.disconnected(function ()
// setTimeout(function () $.connection.hub.start(); , 5000); // Restart connection after 5 seconds.
//);
$.connection.hub.disconnected(function ()
$("#hubStatus").html("Disconnected");// you can restart on here.
$("#btnHub").text("Stat Again after reload window");
);
);
function clientMethods(proxyHub)
//proxyHub.on('onConnected', function (sendTimeLimit)
// sendTimeLimit = sendTimeLimit;
//);
proxyHub.on('onNewUserConnected', function (serverItem)
sendTimeLimit = serverItem;
sessionTime = sendTimeLimit * 1000;
);
proxyHub.on('startSendingClient', function (serverItem)
//Logic after start sending data.
var name = serverItem.name;
var status = serverItem.status;
$("#hubStatus").html(status);
$("#counter").html(sendTimeLimit);
timeCounter();
startTimer(proxyHub, name );
);
proxyHub.on('forceStopClint', function (serverItem)
clearClintPendingTask(serverItem);//Logic before proxy stop.
$("#btnHub").text("Force Stop...");
$.connection.hub.stop();
);
proxyHub.on('onUserDisconnected', function (serverItem)
//Logic after proxy Disconnected (time out).
$("#hubStatus").html(serverItem);
$("#btnHub").text("Stat Again after reload window");
);
//Logic before proxy stop.
function clearClintPendingTask(status)
//do all you need
$("#hubStatus").html(status);
stopTimer();
function startTimer(proxyHub,data)
stopTimer();
proxyTimer = setTimeout(function ()
proxyHub.server.forceStopServer(data);
, sessionTime);
function stopTimer()
if (proxyTimer)
clearTimeout(proxyTimer);
proxyTimer = null;
function timeCounter()
var counter = sendTimeLimit;
var interval = setInterval(function ()
counter--;
$("#counter").html(counter);
if (counter == 0)
//Do something
$("#counter").html("Countdown ended!");
// Stop the counter
clearInterval(interval);
, 1000);
(已测试)
【讨论】:
【参考方案3】:您需要定义超时。在服务器上你可以设置 DisconnectTimeout,像这样:
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromMinutes(30);
https://zzz.buzz/2016/05/11/setting-timeout-for-signalr-for-easier-debugging/
【讨论】:
正如我所说,来自前端站点的请求尚未完成,因此前端仍有一些数据要发送到 SignalR-Backend/Hub。所以我正在寻找前端解决方案。【参考方案4】:更新编辑,请参阅下面的选项 3。 所有其他人都依赖超时,我发布了强制断开连接。
如果您正在尝试强制断开连接 - 您可以获取已连接用户的列表并在服务器端调用 ForceLogOut
函数,我在代码项目的某个地方看到了这个,希望对您有所帮助。如果您只想强制注销/杀死某些用户,只需循环并仅终止该连接即可。
服务器端
public class User
public string Name get; set;
public HashSet<string> ConnectionIds get; set;
public class ExtendedHub : Hub
private static readonly ConcurrentDictionary<string, User> ActiveUsers =
new ConcurrentDictionary<string, User>(StringComparer.InvariantCultureIgnoreCase);
public IEnumerable<string> GetConnectedUsers()
return ActiveUsers.Where(x =>
lock (x.Value.ConnectionIds)
return !x.Value.ConnectionIds.Contains
(Context.ConnectionId, StringComparer.InvariantCultureIgnoreCase);
).Select(x => x.Key);
public void forceLogOut(string to)
User receiver;
if (ActiveUsers.TryGetValue(to, out receiver))
IEnumerable<string> allReceivers;
lock (receiver.ConnectionIds)
allReceivers = receiver.ConnectionIds.Concat(receiver.ConnectionIds);
foreach (var cid in allReceivers)
// ***************** log out/KILL connection for whom ever your want here
Clients.Client(cid).Signout();
客户端
// 1- Save your connection variable when you start it, and later on you can use it to stop.
var myHubProxy = $.connection.myHub
// 2- Use it when you need to stop it, IF NOT YOU WILL GET AN ERROR
myHubProxy.client.stopClient = function()
$.connection.hub.stop();
;
// With a button for testing
$('#SomeButtonKillSignalr').click(function ()
$.connection.hub.stop();
);
使用选项 3 更新:根据请求...其他解决方案依赖于超时,但您也可以直接强制通过自行处理连接 p>
我打开 SignalR 代码,在里面你可以看到 DisposeAndRemoveAsync
客户端连接的实际终止。
1- 您可以通过您的连接修改或致电DisposeAndRemoveAsync
。
2- 然后拨打RemoveConnection(connection.ConnectionId);
public async Task DisposeAndRemoveAsync(HttpConnectionContext connection)
try
// this will force it
await connection.DisposeAsync();
catch (IOException ex)
_logger.ConnectionReset(connection.ConnectionId, ex);
catch (WebSocketException ex) when (ex.InnerException is IOException)
_logger.ConnectionReset(connection.ConnectionId, ex);
catch (Exception ex)
_logger.FailedDispose(connection.ConnectionId, ex);
finally
// Remove it from the list after disposal so that's it's easy to see
// connections that might be in a hung state via the connections list
RemoveConnection(connection.ConnectionId);
注意,完成后请自行清理。
【讨论】:
正如我所说,$.connection.hub.stop()
-Function 会引发错误,因为请求尚未完全发送到后端。因此,我正在寻找一种解决方案,即使存在正在运行的请求,也会终止当前活动的连接。如何从angularJs连接signalR
】如何从angularJs连接signalR【英文标题】:HowtoconnectsignalRfromangularJs【发布时间】:2017-02-0100:50:02【问题描述】:我在.NET中将Web应用程序开发为两个独立的应用程序,后端使用webapic#,用户界面使用AngularJS。我只想在这个项目中添... 查看详情
如何确定与 SignalR 客户端的服务器断开连接?
】如何确定与SignalR客户端的服务器断开连接?【英文标题】:HowtodetermineserverdisconnectionfromSignalRclient?【发布时间】:2012-02-2410:36:18【问题描述】:SignalRJavaScript客户端如何检测与服务器的连接何时丢失?【问题讨论】:你在asp.ne... 查看详情
SignalR:服务器如何建立与客户端的连接?
】SignalR:服务器如何建立与客户端的连接?【英文标题】:SignalR:howServercanestablishconnectiontoClient?【发布时间】:2017-05-1110:43:18【问题描述】:有没有可能实现这种逻辑:服务器与客户端建立连接。那么客户端使用这个连接向服... 查看详情
SignalR Client 开始连接时如何设置用户?
】SignalRClient开始连接时如何设置用户?【英文标题】:SignalRClientHowtoSetuserwhenstartconnection?【发布时间】:2015-06-1302:25:27【问题描述】:服务器端:publicoverrideTaskOnConnected()varconnectionId=Context.ConnectionId;varuser=Context.User.Identity.Name;// 查看详情
使用一个连接发送并发 SignalR 消息
】使用一个连接发送并发SignalR消息【英文标题】:SendconcurrentSignalRmessageswithoneconnection【发布时间】:2022-01-0611:56:43【问题描述】:如何仅通过一个连接并行发送多条SignalR消息?我有以下集线器方法:publicasyncTaskTest()Console.WriteLi... 查看详情
SignalR:检测客户端上的连接状态
】SignalR:检测客户端上的连接状态【英文标题】:SignalR:detectconnectionstateonclient【发布时间】:2012-03-0905:48:02【问题描述】:我已经了解了如何通过绑定到.disconnect事件来使用SignalR在客户端捕获断开连接事件。现在我已经完成了... 查看详情
如何从signalr客户端端确定服务器断开连接
...t;disconnected");对持续连接可以覆盖OnDisconnectAsync,(从SignalR维基于)publicclassMyEndPoint:PersistentConnectionprotectedoverrideTaskOnDisconnectAsync(stringclientId)returnConnection.Broadcast("Client"+clientId+"disconncte 查看详情
如何使用 SignalR 加入群组
】如何使用SignalR加入群组【英文标题】:HowtojoinagroupusingSignalR【发布时间】:2013-06-2223:35:07【问题描述】:我是使用SignalR的新手(从今天开始),向所有连接的客户端发送消息非常简单,但现在我只想发送给一个组。我找不到... 查看详情
如何通过 SignalR 实现“谁在打字”功能?
】如何通过SignalR实现“谁在打字”功能?【英文标题】:Howtoimplement\'Whoistyping\'featureviaSignalR?【发布时间】:2014-11-0317:14:29【问题描述】:基本上,我正在我的网站中实现SignalR聊天。我已经可以向所有连接的用户发送消息,现... 查看详情
signalr设计理念(代码片段)
SignalR设计理念(二)实现客户端和服务器端的实时通讯.前言:客户端方法忽略大小写,主要原因基于是URL对大小写不敏感的问题,开发者之间为了更好的协同开发,定下的开发者协议。问题阐述客户端数量不确定!同一个用户的客... 查看详情
signalr和node.js哪个好
在你使用signalR的过程中一定已经注意到了,前端页面除了加载signalR外还需要加载~/signalr/hubs下的js文件。该自动生成的文件指明了signalR客户端该如何访问后端。当前端的signalRClient执行connect方法时其与后端建立了一个连接(连接... 查看详情
Blazor WebAssembly SignalR 身份验证
】BlazorWebAssemblySignalR身份验证【英文标题】:BlazorWebAssemblySignalRAuthentication【发布时间】:2020-09-1608:28:49【问题描述】:我希望看到有关如何使用Blazor的WebAssembly风格向SignalR集线器连接添加身份验证的示例。我的dotnet版本是3.1.300... 查看详情
SignalR .Net Core 多连接
】SignalR.NetCore多连接【英文标题】:SignalR.NetCoreMultipleConnection【发布时间】:2020-08-1712:25:44【问题描述】:您好,我的应用程序后端是.NETCore,前端是Angular2+。我有一页,两个人既可以聊天又可以查看图表中的报告。我想用signalR... 查看详情
signalR 背板是不是也共享连接?
】signalR背板是不是也共享连接?【英文标题】:DoessignalRbackplanesharesconnectionsalso?signalR背板是否也共享连接?【发布时间】:2015-06-0112:05:34【问题描述】:signalR背板是否也共享连接信息?我的意思是在“longpolling”的情况下,连... 查看详情
SignalR 和 OpenId 连接
】SignalR和OpenId连接【英文标题】:SignalRandOpenIdConnect【发布时间】:2017-04-0922:11:20【问题描述】:我有一个使用ASP.NETCoreWebApi和OpenIddict作为授权框架的服务器。现在我添加了一个SignalR主机,并想为其添加授权。从differentsources我... 查看详情
SignalR 和 OpenId 连接
】SignalR和OpenId连接【英文标题】:SignalRandOpenIdConnect【发布时间】:2017-04-0922:11:20【问题描述】:我有一个使用ASP.NETCoreWebApi和OpenIddict作为授权框架的服务器。现在我已经添加了一个SignalR主机,并想为其添加授权。从differentsourc... 查看详情
SignalR:为啥选择集线器与持久连接?
】SignalR:为啥选择集线器与持久连接?【英文标题】:SignalR:WhychooseHubvs.PersistentConnection?SignalR:为什么选择集线器与持久连接?【发布时间】:2012-03-0600:47:56【问题描述】:我最近一直在搜索和阅读SignalR,虽然我看到很多关于... 查看详情
如何在 ng2-signalr 中设置授权标头?
】如何在ng2-signalr中设置授权标头?【英文标题】:HowtosetAuthorizationHeaderinng2-signalr?【发布时间】:2017-10-3121:24:49【问题描述】:我在ionic2中使用库ng2-signalr。问题是我不知道如何设置授权标头。我已经搜索但没有找到任何示例。... 查看详情