我有一个SignalR Hub和一个.net Xamarin Android客户端。 当使用稳定的互联网连接时,它们可以正常工作,客户端可以发送到集线器,集线器可以发送给客户端。
然而,客户似乎无法自动重新连接(与在线文档所说的相反),并且由于以下问题,尝试自行重新连接是不可能的。
如果客户端成功启动HubConnection,则状态从Disconnected开始 - >连接 - >连接的。但是,如果您从客户端拔出网络电缆,那么无法它就可以到达服务器。状态从未(并且我的意思是永远)从“已连接”更改。
我确实得到了一个“ConnectionSlow”事件,但连接状态永远不会改变,并且在连接上调用Start没有任何作用,因为查看signalR源代码,在内部检查状态是否!=“已连接”,如果不是,它只是返回。 SignalR Github Source Code
我的问题是,您是如何建立与服务器的SignalR连接并让它(或实现)自动重新连接。因为我没有尝试过任何工作。
答案 0 :(得分:0)
我不确定这是否会对你有所帮助,但请注意:
在信号器断开连接后(即网络断开连接),我发现最好创建一个新的连接集线器。不要指望信号器总是重新连接(它将尝试几秒钟,然后再见再连接)。
如果要关闭当前连接,请不要尝试关闭它(signalR可能会在实际释放连接之前冻结大约20秒。只需将连接变量重新设置为新连接。
这是我的工作代码:
private async Task Connect(bool dismissCurrentConnection = false)
{
// Always create a new connection to avoid SignalR close event delays
if (connection != null)
{
if (!dismissCurrentConnection)
{
return;
}
connection.StateChanged -= OnConnectionStateChangedHandler;
connection.Reconnected -= OnReconnectedHandler;
// DON´T call connection.Dispose() or it may block for 20 seconds
connection = null;
proxy = null;
}
connection = new HubConnection(Settings.SERVER);
// connection.TransportConnectTimeout = TimeSpan.FromSeconds(5);
connection.TraceWriter = tracer;
connection.TraceLevel = TraceLevels.All;
connection.StateChanged += OnConnectionStateChangedHandler;
connection.Reconnected += OnReconnectedHandler;
proxy = connection.CreateHubProxy("ChatHub");
proxy.On<ChatMessage>("AddNewMessage", message => AddNewMessage(message));
proxy.On<ChatMessage>("ConfirmMessageDelivered", Message => ConfirmMessageDelivered(Message));
proxy.On<string>("ConfirmMessageReceived", uid => ConfirmMessageReceived(uid));
proxy.On<string>("ConfirmMessageRead", uid => ConfirmMessageRead(uid));
proxy.On<UserChatStatus>("ChangeUserChatStatus", status => ChangeUserChatStatus(status));
if (connection.State == ConnectionState.Disconnected)
{
try
{
MvxTrace.Trace("[{0}] Connecting...", nameof(ChatService));
await connection.Start();
await invokeQueue.ProcessQueue();
}
catch (Exception ex)
{
MvxTrace.Error("[{0}] CONNECTION START ERROR: {1}", nameof(ChatService), ex.Message);
}
}
}
我第一次连接await Connect(); 后续连接将使用await Connect(true)来关闭当前连接
private void OnReconnectedHandler()
{
Task.Factory.StartNew(async () => await invokeQueue.ProcessQueue());
}
private void OnConnectionStateChangedHandler(StateChange change)
{
this.ConnectionState = change.NewState;
OnConnectionStateChanged?.Invoke(change);
switch (change.NewState)
{
case ConnectionState.Disconnected:
// SignalR doesn´t do anything after disconnected state, so we need to manually reconnect
reconnectTokenSource = new CancellationTokenSource();
Task.Factory.StartNew(async () =>
{
await Task.Delay(TimeSpan.FromSeconds(Settings.RECONNECT_PERIOD_SECONDS), reconnectTokenSource.Token);
await Connect(true);
}, reconnectTokenSource.Token);
break;
}
}
如果您想知道什么是“invokeQueue”,它只是一个自定义实用程序,在状态未连接时捕获所有信号器代理调用,并在连接恢复后处理它们。
“reconnectTokenSource”将被取消,以防我不希望重新连接过程继续进行(即:关闭活动时)。
看起来我们都有非常相似的配置。唯一明显的区别是你在Android项目中使用nuget并且我在PCL上使用它。
在此日志中,您可以检查断开连接事件:
mvx:Diagnostic: 14,72 [SignalRTracer] 01:47:56.2406950 - null - ChangeState(Disconnected, Connecting)
mvx:Diagnostic: 15,48 [SignalRTracer] 01:47:57.0176730 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - SSE: GET http://192.168.0.53/signalr/connect?clientProtocol=1.4&transport=serverSentEvents&connectionData=[{"Name":"ChatHub"}]&connectionToken=IgMS6rxmjHJCeudFlDRV8jFSt9Tz1Mt210X21RbiFAIalj%2BioMMRWPH5%2BfNaNIkVW%2BzHbv%2FmSjk8uoRNVbK%2FKUL%2FI87iBkejKkXYivq5FZy6x8E1%2FAK2rBnCg3Zi9nwY&noCache=d4878c0b-5c2a-4535-929c-29952f5e6795
mvx:Diagnostic: 15,56 [SignalRTracer] 01:47:57.0945740 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - SSE: OnMessage(Data: initialized)
mvx:Diagnostic: 15,57 [SignalRTracer] 01:47:57.1054290 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - SSE: OnMessage(Data: {"C":"d-3050D8AB-B,C|I,0|J,1","S":1,"M":[]})
mvx:Diagnostic: 15,70 [SignalRTracer] 01:47:57.2408050 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - ChangeState(Connecting, Connected)
mvx:Diagnostic: 15,82 [SignalRTracer] 01:47:57.3586480 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - SSE: OnMessage(Data: {"C":"d-3050D8AB-B,D|I,0|J,1","M":[]})
mvx:Diagnostic: 15,83 [SignalRTracer] 01:47:57.3718630 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - OnMessage({"I":"0"})
然后我关闭了wifi:
mvx:Diagnostic: 29,55 [SignalRTracer] 01:48:11.0813880 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - OnError(System.Net.Sockets.SocketException: Connection timed out at System.Net.Sockets.Socket.EndReceive (IAsyncResult result) [0x0002d] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:1798 at System.Net.Sockets.NetworkStream.EndRead (IAsyncResult ar) [0x0002f] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/mcs/class/System/System.Net.Sockets/NetworkStream.cs:320 )
mvx:Diagnostic: 31,56 [SignalRTracer] 01:48:13.1037440 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - ChangeState(Connected, Reconnecting)
mvx:Diagnostic: 31,68 [SignalRTracer] 01:48:13.2199720 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - OnError(System.Net.Sockets.SocketException: Network is unreachable at System.Net.Sockets.Socket.Connect (System.Net.EndPoint remoteEP) [0x000bc] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/mcs/class/System/System.Net.Sockets/Socket.cs:1235 at System.Net.WebConnection.Connect (System.Net.HttpWebRequest request) [0x0019b] in /Users/builder/data/lanes/2098/3efa14c4/source/mono/mcs/class/System/System.Net/WebConnection.cs:213 )
稍后......
mvx:Diagnostic: 61,68 [SignalRTracer] 01:48:43.2182200 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - OnError(System.TimeoutException: Couldn't reconnect within the configured timeout of 00:00:30, disconnecting.)
mvx:Diagnostic: 61,69 [SignalRTracer] 01:48:43.2330650 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - Disconnected
mvx:Diagnostic: 61,76 [SignalRTracer] 01:48:43.2972460 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - Transport.Dispose(6dd879af-7d49-4632-96b2-cb5fb542dc24)
mvx:Diagnostic: 61,77 [SignalRTracer] 01:48:43.3065810 - 6dd879af-7d49-4632-96b2-cb5fb542dc24 - Closed