I use Socket.IO 0.9.16 to establish a connection:
io.connect(url)
However, when the server dies, it takes 2 minutes timeout to detect error with the server.
I already tried to reduce timeout to 5s by setting:
io.connect(url, {'timeout': 5000, 'connect_timeout': 5000})
But no success... How can I do this?
The challenge here is that there are a bunch of different settings that interact with each other and some retry logic that all make a socket.io timeout not what you would normally expect. I should add that I am familiar with socket.io 1.0+, not 0.9 though this probably applies to both.
Lets review how a socket.io connection works.
It attempts to make the initial connection.
If that succeeds, then you're done with the connection.
If that connection attempt does not return immediately, it will wait the timeout value that you pass in the initial options for a connection result.
If your server is down, the connection attempt will likely fail quickly. This will result in a connect_error and if you register for that message on the socket with socket.on('connect_error', function() {...});, you will see that connect_error event.
This connect_error is not a timeout. So, if the connection fails quickly (which it usually does when the server is just down), then you never get the regular timeout and the timeout argument you pass to io({timeout: 5000}) really doesn't come into effect. That only comes into effect when a connection to a server is just taking a long time (like an overly busy server or a server that accepted the TCP connection, but is really slow at responding). This is not usually what happens when a server is just down or unreachable.
So, after socket.io gets a connect_error it marks this socket.io connection for retry.
The delay before retrying is based on a whole bunch of things. Presumably, the reconnectionDelay option is part of the formula, but in looking at the code, there is also a backoff algorithm that lengthens the time between retries the more times it has retried. So, suffice it to say, there's some algorithm that calculates a given delay before retrying that varies for each retry.
Then, after that calculated delay, it tries to connect again. This essentially repeats the process starting at step 1 again.
As best I can tell, by default it keeps retrying forever. There is an option you can pass reconnectionAttempts that specifies the maximum number of reconnection attempts. This default to infinity if you don't pass it. But, if you pass 10, then it will give up after 10 successive connection failures.
If you specify reconnectionAttempts, then after that many unsuccessful connection attempts, you will get a reconnect_failed event on the socket and it will give up.
As best I can tell, there is no traditional timeout in the way that you are looking for where it would connect, attempt some retries, then give up after x amount of time. The timeout option applies only to a single reconnect attempt and not to the total amount of time it keeps trying to connect.
In a sample test page I've been experimenting with, I was able to implement my own traditional connection timeout like this:
var socket = io(...);
// set connect timer to 5 seconds
socket._connectTimer = setTimeout(function() {
socket.close();
}, 5000);
socket.on('connect', function() {
// socket connected successfully, clear the timer
clearTimeout(socket._connectTimer);
});
This will wait a maximum of 5 seconds for a successful connection, regardless of how long a connection attempt takes or many reconnect attempts occur in that span of time. After 5 seconds without a successful connection, it shuts down the socket.
In my test app, I can see socket.io happily retrying the connection over and over again until after 5 seconds, my timer fires, I get notified of the "timeout" and I close the socket and it stops trying to retry any more.
I think it is connect timeout
io.connect(url, {'timeout':5000, 'connect timeout': 5000})
Related
I have a working WebRTC JavaScript application. Here is the problem: if during a web call there is a bad network connection, the call is stopped without WebRTC attempting to reconnect.
I would like to improve the code of my application by adding an automatic reconnection attempt system, however, in order to do so I need to understand some theory about WebRTC (and I think this can be very useful for many other developers).
Here are my questions:
Does WebRTC have a native functionality to attempt reconnection if the network is bad or should I listen for some "disconnection tigger" and call "a function" to start a new connection from zero?
If things cannot be done magically, what is/are the right "disconnection tigger/s" and "the function" from which the reconnection attempt process should restart? Is there something that can (or should) be taken from the previous connection?
I have read about an {iceRestart: true} parameter. Should this be used for the first call (then WebRTC will magically handle disconnection by attempting to reconnect) or should I use it ONLY when my code attempts to reconnect (on the 2nd, 3rd times...)?
What is the difference between connectionState "disconnected", "failed" and "closed" and does it have something to do with attempting to reconnect with bad network?
What is the best way to avoid attempting to reconnect in an infinite loop if there is no hope to reconnect (i.e: internet completely down)?
What is the difference between oniceconnectionstatechange and onconnectionstatechange? which is relevant in my case?
Thanks!
Luca
I was able to find the (JavaScript) solution through experimenting...
1) Does WebRTC have a native functionality to attempt reconnection if the network is bad or should I listen for some "disconnection tigger" and call "a function" to start a new connection from zero?
Yes, it does it by default in JavaScript, unless your code handles disconnection by proactively terminating the call through additional lines of instructions.
2) If things cannot be done magically, what is/are the right "disconnection tigger/s" and "the function" from which the reconnection attempt process should restart? Is there something that can (or should) be taken from the previous connection?
Things already happen under the hood (by magic). If the code terminates the call, it is probably because the disconnection trigger (ICE connection state = disconnected OR connection state = disconnected) triggers some additional code from the app you copy/pasted from somewhere.
3) I have read about an {iceRestart: true} parameter. Should this be used for the first call (then WebRTC will magically handle disconnection by attempting to reconnect) or should I use it ONLY when my code attempts to reconnect (on the 2nd, 3rd times...)?
Not useful in this scenario.
4) What is the difference between connectionState "disconnected", "failed" and "closed" and does it have something to do with attempting to reconnect with bad network?
You have to listen for connectionState = disconnected, the other ones don't matter for this purpose.
5) What is the best way to avoid attempting to reconnect in an infinite loop if there is no hope to reconnect (i.e: internet completely down)?
No problem, the reconnection WebRTC handles automatically will not cost anything in terms of signaling, therefore, you can try to reconnect as many times as you want, the user will eventually exit the call on his own if things are too slow.
6) What is the difference between oniceconnectionstatechange and onconnectionstatechange? which is relevant in my case?
No difference in this case, the only difference is that the ice state change is triggered right before the connection state change.
--
I hope this will be helpful to somebody!
I have a webapp to test. I got a test working with protractorJS that is clicking different buttons.
Some buttons do trigger a POST request, and the webapp is waiting for an answer from that point on. The answer can take up to 30 or 40 seconds to come in. If I look into the Chrome Developer tools, I see that the webapp sends GET packets to get the status every 2 seconds. The status can be waiting, failed or successful.
My Question is now:
How can I watch the network traffic and filter them that I know at which point the successful or failed status packet comes in?
I found PhantomJS Network Monitoring.
Basically I want to call a function after I clicked the button automatically with protractor, and this function should look into every packet that is coming in and should stop when it reads that the status is successful. If it takes more than 60 or 70 seconds the function should time out.
After clicking the button which triggers POST method you should start listening in a loop another endpoint (GET) every n seconds (you wrote that app does it every 2 seconds).
If status is waiting - keep going, if it's failed - raise an exception and fail the test, if it successful - pass the test or do whatever you want.
The loop will prevent you from timeout.
You need to consider whether you need to protect yourself from the infinite loop if e.g. worker which processes the task stops working. Then GET method may return waiting, the loop won't finish and the test won't stop.
Maximum HTTP Request execution time is 120sec in Node.js , how can i increase max execution time on http get/post requests?
NOTE:I'm using expressjs framework
http://nodejs.org/api/http.html#http_server_timeout
server.timeout
Number Default = 120000 (2 minutes)
The number of milliseconds of inactivity before a socket is presumed to have timed out.
Note that the socket timeout logic is set up on connection, so changing this value only affects new connections to the server, not any existing connections.
Set to 0 to disable any kind of automatic timeout behavior on incoming connections.
You would use server.setTimeout(0); to get what you're after. It's documented here. Although I can't figure out why you would need to change this except for troubleshooting.
It is common for laptops to go to sleep. This causes the socket.io client to disconnect. When the user returns to the web app, the socket.io client doesn't try to reconnect (probably reconnection limit reached?). How do I tell the socket to reconnect if the user does some action?
For example, I'd like the emit function to check if the connection is active, and if not then try to reconnect.
Note: I only need the client-side JS code and I'm not using node.js.
In version 0.9 you could try to set the connect options object to some aggressive settings:
var main = io.connect('/', {
'reconnection delay': 100, // defaults to 500
'reconnection limit': 100, // defaults to Infinity
'max reconnection attempts': Infinity // defaults to 10
});
Note that max reconnection attemps does not mean that the io client will stop to reconnect to the server after 10 failed attempts. If it was able to reconnect to the server 10 times and loses the connection for the 11th time, it will stop to reconnect.
See Socket.IO Configuration
Socket instances have an inner 'socket' property, which in turn has connect() method that you can call. It's normally called automatically when you instantiate the object (controlled by the 'auto connect' option). The inner socket also have a boolean "connected" property which you can check if you're not sure what the state is. Like so:
sio = io.connect();
//... time passes ...
if (! sio.socket.connected) {
sio.connect();
}
The connect() method checks to make sure that the socket isn't in the middle of trying to connect, though for some reason it doesn't check to see if it's already connected. Not sure what happens if you connect() an already-connected socket...
The source code for the client library is fairly clear and well commented, which is good since the README on github doesn't provide a whole lot of help. It's handy to use an un-minified version of the library while you're doing development so you can dig into the source.
You could try to use the connect.failed event:
socket.on('connect_failed', function () {
/* Insert code to reestablish connection. */
});
You could have a setInterval running which checks connected status like
s.connect()
if (! s.socket.connected) {
s.connect();
I need to be able to detect when a user has lost connection to the socket, it doesn't seem that socket.on("disconnect") is being called when I just close my laptop, so it doesn't run the ajax call that needs to run in order to update the database to mark the user as offline. How could I check if the connection has been closed or whatever?
As mentioned here https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO, Socket.IO has it's own heartbeat implementation.
But the defaults are a 25s interval and a 60s threshold for a lost connection.
So my advice: Set the defaults as you expect on testing. Otherwise you may miss the threshold.
Example:
socket.set("heartbeat timeout", 10);
socket.set("heartbeat interval", 5);
we came across this too and as mentioned above use our own heartbeat timer.
For example the server will emit a heartbeat every 5 seconds (we simple send out server time). The client has an 11 second timeout so it has 2 chances to catch the heartbeat. If it receives the heartbeat we reset the timer. If we miss both heartbeats the timeout function is run and you do whatever you want there.
Fairly straightforward.