I have developed simple chat system using signal R.
In case when internet is disconnect and reconnect after 2 minutes all signal r server methods are invoking but client methods are not getting response.
Can some one tell me what can I do for that?
If the internet disconnects so does the signalR client. You will need to handle reconnecting. The below code is the example from the site below to show you how to handle signalR continuously trying to reconnect in case a disconnect happens.
$.connection.hub.disconnected(function() {
setTimeout(function() {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
More information can be found here: http://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events
Related
I have this code to test asynchronous programming in SignalR. this code send back to client the text after 10 seconds.
public class TestHub : Hub
{
public async Task BroadcastMessage(string text)
{
await DelayResponse(text);
}
async Task DelayResponse(string text)
{
await Task.Delay(10000);
Clients.All.displayText(text);
}
}
this code work fine but there is an unexpected behavior. when 5 messages are sent in less than 10 second, client can't send more message until previous "DelayResponse" methods end. it happens per connection and if before 10 seconds close the connection and reopen it, client can send 5 messages again. I test it with chrome, firefox and IE.
I made some mistake or it is signalr limitation?
You are most likely hitting a browser limit. When using longPolling and serverSentEvent transport each send is a separate HTTP request. Since you are delaying response these requests are longer running and browsers have limits of how many concurrent connection can be opened. Once you reach the limit a new connection will not be open until one of the previous ones is completed.
More details on concurrent requests limit:
Max parallel http connections in a browser?
That's not the sens of signalR, that you waiting for a "long running" task. For that signalR supports server push mechanisme.
So if you have something which needs more time you can trigger this from client.
In the case the calculation is finish you can send a message from server to client.
In the offline capabilities section for Web, it is described here how to detect if the client is connected to the internet or not. However, Firebase doesn't seem to call the event handler every time a client connects or disconnects when running in Node environment. It works as expected when running in the browser i.e. it calls the event handler every time the client is connected or disconnected from the internet.
Check out this jsFiddle. Once you run the fiddle and you connect or disconnect from the internet, you will see a corresponding 'connected' or 'disconnected' message in the console.
I ran the below code in Node which is exactly same as the code I ran in browser. While running in Node environment, I observed that I received the initial 'connected' and 'disconnected' message but if I connected and disconnected from the internet again, no messages are printed meaning that the event handler is not called
var Firebase = require('firebase');
var ref = new Firebase("<FIREBASE-APP>");
var connectedRef = ref.child(".info/connected");
connectedRef.on("value", function(snap) {
if (snap.val() === true) {
console.log("connected");
} else {
console.log("not connected");
}
});
I just ran the same script in node on my system:
$ node connected.js
not connected
connected
not connected
connected
The first two come from the initial start of the script. The last two log lines came after I turned the wifi of my laptop off for a minute and then on again.
It may take some time before the Firebase client detects that it lost the connection to its servers, so be patient. The reason for the time it takes depends on the environment (browser/node) you run in, since the Firebase client depends on that environment to provide the WebSocket and detect time-outs.
Using a SignalR persistent connection with a JS long polling client we see inconsistent reconnection behavior in different scenarios. When the client machine's network cable is unplugged the JS connection does not enter the reconnecting state and it never (at least not after 5 minutes) reaches the disconnected state. For other scenarios such as a restart of the IIS web application a long polling JS connection does enter the reconnecting state and successfully reconnects. I understand that the reasoning behind this is that keep-alive is not supported for the long polling transport.
I can see that a suggestion has been made on github to better support reconnections for the long polling transport (https://github.com/SignalR/SignalR/issues/1781), but it seems that there is no commitment to change it.
First, is there a proper workaround for detecting disconnections on the client in the case of long polling.
Second, does anyone know if there are plans to support reconnection in the case described?
Cheers
We've debated different alternatives to support a keep alive "like" feature for long polling; however, due to how long polling works under the covers it's not easy to implement without affecting the vast majority of users. As we continue to debate the "correct" solution I'll leave you with one work around for detecting network failure in the long polling client (if it's absolutely needed).
Create a server method, lets call it ping:
public class MyHub : Hub
{
public void Ping()
{
}
}
Now on the client create an interval in which you will "ping" the server:
var proxy = $.connection.myHub,
intervalHandle;
...
$.connection.hub.disconnected(function() {
clearInterval(intervalHandle);
});
...
$.connection.hub.start().done(function() {
// Only when long polling
if($.connection.hub.transport.name === "longPolling") {
// Ping every 10s
intervalHandle = setInterval(function() {
// Ensure we're connected (don't want to be pinging in any other state).
if($.connection.hub.state === $.signalR.connectionState.connected) {
proxy.server.ping().fail(function() {
// Failed to ping the server, we could either try one more time to ensure we can't reach the server
// or we could fail right here.
TryAndRestartConnection(); // Your method
});
}
}, 10000);
}
});
Hope this helps!
I have two meteor applications connected via DDP on different servers and server A send data to server B. This is the way they work.
Server A
Items = new Meteor.Collection('items');
Items.insert({name: 'item 1'});
if (Meteor.isServer) {
Meteor.publish('items', function() {
return Items.find();
});
}
Server B
var remote = DDP.connect('http://server-a/');
Items = new Meteor.Collection('items', remote);
remote.subscribe('items');
Items.find().observe({
added: function(item) {
console.log(item);
}
});
Every time I call Items.insert(something) on server A, on Server B I got a log on the console with the object I saved on Server A. But if Server B lost Internet connection, the data inserted on Server A doesn't appear anymore on Server B when it reconnect to Internet.
Server B is connected to Internet through a router. This problem only happen when I disconnect and reconnect the router, not when I disconnect and reconnect the server from the router. Both servers are on different networks and connect via Internet.
I created a timer on Server B that call remote.status() but always get { status: 'connected', connected: true, retryCount: 0 } when connected or disconnected from Internet.
Update: steps to reproduce
I created a project on github with the testing code https://github.com/camilosw/ddp-servers-test. Server A is installed on http://ddpserverstest-9592.onmodulus.net/
My computer is connected to Internet through a wireless cable modem.
Run mrt on server-b folder
Go to http://ddpserverstest-9592.onmodulus.net/ and click the link Insert (you can click delete to remove all previous inserts). You must see a message on your local console with the added item.
Turn off the wireless on the computer and click the insert link again. (You will need to click on another computer with Internet access, I used an smartphone to click the link)
Turn on the wireless on the computer. You must see a message on your local console with the second item.
Now, turn off the cable modem and click the insert link again.
Turn on the cable modem. This time, the new item doesn't appear on the console.
I also did it with an android smartphone using the option to share Internet to my computer via wireless. First I turned off and on the wireless on my computer and worked right. Then I turned off and on the Internet connection on the smartphone and I got the same problem.
Update 2
I have two wireless router on my office. I found that the same problem happen if I move between routers.
Emily Stark, from the Meteor Team, confirmed that this is due to a missing feature on the current implementation (version 0.7.0.1 at the moment I write this answer). Their answer is here https://github.com/meteor/meteor/issues/1543. Below is their answer and a workaround she suggest:
The server-to-server connection is not reconnecting because Meteor currently doesn't do any heartbeating on server-to-server DDP connections. Just as in any other TCP connection, once you switch to a different router, no data can be sent or received on the connection, but the client will not notice unless it attempts to send some data and times out. This differs from browser-to-server DDP connections, which run over SockJS. SockJS does its own heartbeating that we can use to detect dead connections.
To see this in action, here is some code that I added to server-b in your example:
var heartbeatOutstanding = false;
Meteor.setInterval(function () {
if (! heartbeatOutstanding) {
console.log("Sending heartbeat");
remote.call("heartbeat", function () {
console.log("Heartbeat returned");
heartbeatOutstanding = false;
});
heartbeatOutstanding = true;
}
}, 3000);
remote.onReconnect = function () {
console.log("RECONNECTING REMOTE");
};
With this code added in there, server-b will reconnect after a long enough time goes by without an ACK from server-a for the TCP segments that are delivering the heartbeat method call. On my machine, this is just a couple minutes, and I get an ETIMEDOUT followed by a reconnect.
I've opened a separate task for us to think about implementing heartbeating on server-to-server DDP connections during our next bug week. In the meantime, you can always implement heartbeating in your application to ensure that a DDP reconnection happens if the client can no longer talk to the server.
I think you are not passing DDP connection object to the Collection correctly, try:
var remote = DDP.connect('http://server-a/');
Items = new Meteor.Collection('items', { connection: remote });
It might be useful for debugging to try all these connection games from the browser console first, since Meteor provides the same API of connection/collections on the client (except for the control flow). Just open any Meteor application and try this lines from the console.
I revised a sample of communication between two ddp server, based on camilosw's code.
Server A as Cloud Data Center. Server B as Data Source, if some data changed, should be send to Server A.
You can find the code from https://github.com/iascchen/ddp-servers-test
So I have signalr working all fine, pushing my data to the client no problems. I implemented my own keep alive using an ajax call to keep the connection alive. But I have been reading and there is the option that I am trying:
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(30);
But my issue is if it fails to send the keep alive how do you capture it on the javascript end?
If this is the server pushing data to keep the connection alive does that mean the client will never know if it has failed?
Or will the javascript throw a connection.error?
I want to be able to pull the clients network cable out, and after XX seconds it display a message saying network connection lost. Atm I have this working using my ajax call but is this possible using the keepalive value?
This is already implemented for every transport except LongPolling.
By default the JS client will go into reconnecting if it has missed 2 keep alives.
If you want to tie into the reconnecting event you can do:
$.connection.hub.reconnecting(function() {
// Your logic
});
If you want to tie into the event that indicates that the connection MAY go into reconnecting can do:
$.connection.hub.connectionSlow(function() {
// Your logic
});
Keep in mind by default the client will stop trying to reconnect after a given time and will shift into the disconnected state to avoid unnecessary reconnect events. If you want to ensure that your connection is ALWAYS connected, even if there's down time see my answer here: Client Reconnection