signalr not working on specific isp networks - asp.net

I'm using ASP.NET MVC 4 and SignalR 2.1.1.
My website works great for most users in all browsers, but there is an error that only occurs for certain user on specific isp-networks.
The error is this:
The connection to ws://domain.com/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=78ZpJ007jmlLSBbVzDVbfpYahHsveD3x8%2Bc5PC9h%2FgeOz5zNgE8SaKWaQAasGNLe%2BvJeI6ux6IqW0E8WQWqP6Ps%2FXjc8WPbG7G47oHSxRSx7nVj0leVa1DdXzEXnLQ%2BA&connectionData=%5B%7B%22name%22%3A%22homehub%22%7D%5D&tid=4 was interrupted while the page was loading.
For the same users receiving this error, logging in the internet using a different network (while same browser / computer / cellphone) fixes the problem.
Up until now I only saw questions about this error that points the problem to the browser, however in my case, using the same browser with a different network fixes the problem.
Any chance any of you knows how to fix this?
UPDATE 1:
I noticed that client methods actually works, it's the server methods that don't work.
What do I mean?:
I have a list of online users, and upon user entering & exiting the site, a signalr client method that updates the list of usernames is called:
hub.client.addOnlineMember = function (member) {
var newMember = addMember(member);
memberList.append(newMember);
};
hub.client.removeOnlineMember = function (member) {
var newMemberId = '#' + member;
$(memberListName + ' ' + newMemberId).remove();
};
However when trying to load messages from the server, it's functions don't work:
$('#LoadMore').click(function () {
hub.server.loadTopics(page);
});
UPDATE 2:
I added logging:
$.connection.hub.logging = true;
Here are the findings:
The connection to ws://domain.com/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=rR8%2BSK%2BC%2FtuzPqIGKgPrUNORzBz2kP0WUmXJsURP70Zsj6RK1fOi5tUN1UGEQPntGwoEvwinMkPCXRTyliLwzfLoOBl%2BkCWoBAkAqIFYaDVk3X1MG8dQERl8Or%2F4%2Filp&connectionData=%5B%7B%22name%22%3A%22hub%22%7D%5D&tid=6 was interrupted while the page was loading. jquery.signalr-2.1.1.min.js:8
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help http://xhr.spec.whatwg.org/ jquery-2.1.1.min.js:4
"[16:21:50] SignalR: Stopping connection." jquery.signalr-2.1.1.min.js:8
"[16:21:50] SignalR: Closing the Websocket." jquery.signalr-2.1.1.min.js:8
no element found abort:1
"[16:21:50] SignalR: Fired ajax abort async = false." jquery.signalr-2.1.1.min.js:8
"[16:21:50] SignalR: Stopping the monitoring of the keep alive." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: Client subscribed to hub 'hub'." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: Negotiating with '/signalr/negotiate?clientProtocol=1.4&connectionData=%5B%7B%22name%22%3A%22hub%22%7D%5D'." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: Connecting to websocket endpoint 'ws://domain.com/signalr/connect?transport=webSockets&clientProtocol=1.4&connectionToken=bkg5ksXTUdzl9GrShmLqEyUbeG9SMDBaiccbH2prQ4t1mPmoOutKqj9gvgkd9vveTnIKhK0cMHYZ8NOrS4pemaLmwOb5TmNJzGEiPAUXrknuIhxtUSqmNmL255MIFdwc&connectionData=%5B%7B%22name%22%3A%22hub%22%7D%5D&tid=2'." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: Websocket opened." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: webSockets transport selected. Initiating start request." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: The start request succeeded. Transitioning to the connected state." jquery.signalr-2.1.1.min.js:8
"[16:21:51] SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332 and a connection lost timeout of 20000." jquery.signalr-2.1.1.min.js:8
"[16:23:05] SignalR: Triggering client hub event 'addOnlineMember' on hub 'hub'." jquery.signalr-2.1.1.min.js:8
"[16:23:25] SignalR: Triggering client hub event 'removeOnlineMember' on hub 'hub'." jquery.signalr-2.1.1.min.js:8
"[16:23:42] SignalR: Invoking hub.LoadTopics" jquery.signalr-2.1.1.min.js:8
As you can see, client methods works great. Server method is being invoked but nothing happens.
Logging signalr on a working isp network:
"[17:03:40] SignalR: Invoking hub.LoadTopics" jquery.signalr-2.1.1.min.js:8
"[17:03:41] SignalR: Triggering client hub event 'addTopicToHome' on hub 'hub'." jquery.signalr-2.1.1.min.js:8
"[17:03:41] SignalR: Triggering client hub event 'incrementPage' on hub 'hub'." jquery.signalr-2.1.1.min.js:8
"[17:03:41] SignalR: Invoked hub.LoadTopics" jquery.signalr-2.1.1.min.js:8
UPDATE 3:
Upon uploading my project to an IIS 7.5 server, the code works for all ISP networks. Seeing as IIS 7.5 does not support Websockets, protocols such as server-sent-events, long polling and forever frame (depends on the browser) are initiated successfully.
However, I don't know the reason why the IIS 8 server is not initiating a working protocol upon realizing websockets don't work, it's what signalr does, isn't it?
I made contact with my hosting provider, they think the problem has something to do with an unsupported SSL key on the server. This SSL issue still hasn't been fixed by them so there's no way to be sure that's really the problem. Do you think this might be it?
Anyway, still no success in finding an answer.. please help.

Okay its been so long and I was hoping to get help by now, but never mind I mannaged it.
First:
The guys at signalr's channel in Jabbr suggested me to try surfing the website using SSL in hopes it would solve the problem.
I'm afraid I did not have the chance to check that :(
But in case any of you meets the same issue and gets to use SSL approach to solve it, I would deffinitly love to here about it!
And to my answer:
I am taking the user IP and testing if it's in any of the problematic ISP subnets.
If it is, I'm passing my view a parameter, lets say:
bool disableWebsockets = True/False;
If its true, I'm passing signalr a list of transport protocols that does not include websockets. If false - the list does include websockets.
That's it.
function signalrTransportList(wsState) {
if (disableWebsockets == "False") {
var list = ['webSockets', 'serverSentEvents', 'longPolling', 'foreverFrame'];
}
else {
var list = ['serverSentEvents', 'longPolling', 'foreverFrame'];
}
return list;
}
...
...
$.connection.hub.start({ transport: signalrTransportList(wsTransport) })

Related

SignalR .Net 2.4.1-Dead Connection Id Staying Alive

I'm witnessing an odd behavior with my SignalR client (Android). OnDisconnected event is firing, the connection becomes dead, but my hub aborts the event and reissues the connection id as a new connection:
This seems to occur when the Android client goes into a slow state. It's messing up my status indicator on my UI showing that the user is still connected, yet they have logged out. What's the best approach to handle this situation? Should I stop my hub and reconnect when my connection is slow? I thought about getting the connection id from the hub but there's no way to indicate whether or not the connection is alive or dead.
I had a similar situation (using .NET client) and ended up having to implement a heartbeat hub where a simple message (heartbeat) is sent to each client every 15 seconds. The clients have a timer that listens to the heartbeat and resets when it gets a new one.
If two heartbeats are missed, the client closes the connection, waits a few seconds, and opens a new one. There is no way to close a connection from the server. This should allow the server to get the close connection message from the client and actually kill the connection.
Please be aware that the SignalR Java client is no longer maintained. https://github.com/SignalR/java-client#this-repository-is-obsolete-and-no-longer-used-or-maintained.

Signalr Calls are quite large with longPolling transport type - Performance impact

I am using SignalR - transport type longPolling. I am able to see the functionality working as expected. In realtime, I could see there are quite large number of signalR calls which is affecting performance heavily.
It seems, based on my analysis, longPolling creates connection and use it and close it. Then again the connection will be created on demand. I feel, this could be the cause of seeing lot of signalR calls at some point in time.
Could you please share your thoughts on this to resolve / avoid large number of SignalR calls?
When I tried to use foreverFrame as transport type, SignalR connection is not getting enabled. I could see the following error in console.
SignalR: Failed to connect using forever frame source, it timed out after 3000s
SignalR: Stopping forever frame
SignalR: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization
Issue occurred when starting the Signalr Hub.
That appears to be default behavior for long polling based on the docs - Long polling does not create a persistent connection, but instead polls the server with a request that stays open until the server responds, at which point the connection closes, and a new connection is requested immediately. This may introduce some latency while the connection resets.
Your use of foreverFrame may not work because the transport is not available in the browser you are using.
I have yet to understand why anyone would force the transport to a specific one. Possibly, I have just not run into that scenario where it is required.
SignalR will handle the aspect of determining which transport to use with each client, which is one of it's great benefits.

Does SignalR provide message integrity mechanisms which ensure that no messages are lost during client reconnect

Abstract
Hi, I was pondering whether it is possible to loose a message with SignalR. Suppose client disconnects but eventually reconnects in a short amount of time, for example 3 seconds. Will the client get all of the messages that were sent to him while he was disconnected?
For example let's consider LongPolling transport. As far as I'm aware long polling is a simple http request that is issued in advance by the client in order to wait a server event.
As soon as server event occurs the data getting published on the http request which leads to closing connection on issued http request. After that, client issues new http request that repeats the whole loop again.
The problem
Suppose two events happened on the server, first A then B (nearly instantly). Client gets message A which results with closing http connection. Now to get message B client has to issue second http request.
Question
If the B event happened while the client was disconnected from the server and was trying to reconnect.
Will the client get the B message automatically, or I have to invent some sort of mechanisms that will ensure message integrity?
The question applies not only to long-polling but to general situation with client reconnection.
P.S.
I'm using SignalR Hubs on the server side.
EDIT:
I've found-out that the order of messages is not guaranteed, I was not able to make SignalR loose messages
The answer to this question lies in the EnqueueOperation method here...
https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/Transports/TransportDisconnectBase.cs
protected virtual internal Task EnqueueOperation(Func<object, Task> writeAsync, object state)
{
if (!IsAlive)
{
return TaskAsyncHelper.Empty;
}
// Only enqueue new writes if the connection is alive
Task writeTask = WriteQueue.Enqueue(writeAsync, state);
_lastWriteTask = writeTask;
return writeTask;
}
When the server sends a message to a client it calls this method. In your example above, the server would enqueue 2 messages to be sent, then the client would reconnect after receiving the first, then the second message would be sent.
If the server queues and sends the first message and the client reconnects, there is a small window where the second message could attempt to be enqueued where the connection is not alive and the message would be dropped at the server end. Then after reconnect the client wouldn't get the second message.
Hope this helps

When will "OnReconnected" occur?

If "OnConnected" is raised when the 1st time we connect to our website, when will "OnReconnected" happen?
1) Suppose someone is connected to the network and suddenly the network isn't available and soon it recovers, so OnReconnected happens?
2) Any other special that will make OnReconnted happen?
Thanks!
The Signalr documentation on Understanding and Handling Connection Lifetime Events in SignalR should have all the information you need.
Generally speaking OnReconnected will fire any time the SignalR client automatically reconnects to the SignalR server after it has lost its connection for any reason. These reasons can include network issues, the server restarting, etc...
The SignalR client will stop attempting to automatically reconnect to the server if it is unable to successfully do so within the DisconnectTimeout. If this happens, and you want to reestablish a connection, you will be required to manually restart the client by calling start() after the client becomes disconnected. If you manually restart the client by calling start(), OnConnected will be called instead of OnReconnected and the client will receive a new connection id.

Signalr: how does receiving messages from PersistentConnection work internally?

I wonder how does SignalR client receive messages from server after connection has been established? I mean, what happens on the client side internally after Connection.Send(message) method has been invoked?
From reading .NET client code I've found that public event Action<string> Received in Connection class is responsible for receiving messages, but I can't find how it is implemented. I need to know how it works internally because I want to write my own client on Java.
You can read the entire source of signalR on github: https://github.com/SignalR/SignalR
In particular, you can find the source for PersistentConnection - at
https://github.com/SignalR/SignalR/blob/master/src/Microsoft.AspNet.SignalR.Core/PersistentConnection.cs

Resources