60

I construct my websocket connection with this code (e.g.):

var socket = new WebSocket("ws://94.12.176.177:8080");

And I close the connection with this one:

socket.close();

But how do I reestablish connection?

I've done some research and tried several methods. This question could not help me: Socket.io reconnect on disconnect? It's the only result which close to what I'm looking for.

The reason I want to do this is to allow users to stop sending data to the web temporary, and resending again after a period of time. Without reconnection, user have to refresh the page in order to resend. This may cause some data lost. Thank you.

Community
  • 1
  • 1
ket
  • 945
  • 1
  • 9
  • 15
  • Just make a new WebSocket again. The reason a reconnect doesn't exist is because it would probably be just like creating a new one. – AHungerArtist Dec 10 '12 at 08:28
  • 3
    Possible duplicate of *[Reconnection of client when the server reboots in WebSocket](http://stackoverflow.com/questions/3780511/reconnection-of-client-when-server-reboots-in-websocket)*. – Peter Mortensen Jan 28 '17 at 14:35
  • Here is one of the possible solution: https://github.com/gdi2290/angular-websocket/issues/100 – Tomasz Waszczyk Mar 06 '18 at 13:00

5 Answers5

93

When the server closes the connection, the client does not try to reconnect. With some JS frameworks maybe, but the question was, at the time of this answer, tagged as plain Vanilla JS.

I'm a bit frustrated because the accepted, upvoted answer is plainly wrong, and it cost me some additional time while finding the correct solution.

Which is here: Reconnection of Client when server reboots in WebSocket

Community
  • 1
  • 1
SzG
  • 12,333
  • 4
  • 28
  • 41
  • 4
    Sorry for your frustration. The OP links to a `socket.io` question, and that must have been the framework he was using. The question should be tagged `socket.io`. – Jivings Jul 01 '16 at 09:58
  • Thank you for the link; it did the trick. The accepted answer did not make sense as I am working on a websocket without a framework. – Chad Sep 14 '16 at 01:22
  • 2
    The ansver you point to does essentially the same what @Jivings suggests. Except this one doesnt mention `socket.close` instance method. – aegyed Nov 01 '16 at 21:44
35

I found a great solution on this page: https://sam-low.com/how-to-reopen-a-closed-websocket.html

Once the original connection has been closed, you need to create a new WebSocket object with new event listeners

function startWebsocket() {
  var ws = new WebSocket('ws://localhost:8080')

  ws.onmessage = function(e){
    console.log('websocket message event:', e)
  }

  ws.onclose = function(){
    // connection closed, discard old websocket and create a new one in 5s
    ws = null
    setTimeout(startWebsocket, 5000)
  }
}

startWebsocket();

Note that if there’s a problem reconnecting, the new WebSocket object will still receive another close event, meaning that onclose() will be executed even if it never technically opened. That’s why the delay of five seconds is sensible - without it you could find yourself creating and destroying thousands of websocket connections at a rate that would probably break something.

ADTC
  • 8,999
  • 5
  • 68
  • 93
Pol
  • 350
  • 3
  • 6
14

NOTE: The question is tagged socket.io so this answer is specifically regarding socket.io.
As many people have pointed out, this answer doesn't apply to vanilla websockets, which will not attempt to reconnect under any circumstances.

Websockets will not automatically try to reconnect. You'll have to recreate the socket in order to get a new connection. The only problem with that is you'll have to reattach your handlers.

But really, websockets are designed to stay open.

A better method would be to have the server close the connection. This way the websocket will fire an onclose event but will continue attempting to make the connection. When the server is listening again the connection will be automatically reestablished.

Jivings
  • 22,834
  • 6
  • 60
  • 101
  • 14
    The behaviour where the client socket attempts to reestablish the connection - I guess that's a socketio thing? (not a basic websockets thing?) – UpTheCreek Jun 14 '13 at 12:34
  • 4
    @UpTheCreek Yes I think so. Normal websockets will not try and reconnect if you call `close()` – Jivings Jun 16 '13 at 19:02
  • I was using an open-source pure AS3 implementation of WebSockets and TLS, but I decided the browser's implementation would be kept more up-to-date, so I created a JS WebSocket manager that my AS3 WebSocket class calls. The manager constructs instances with unique IDs and callbacks that forward the event and the socket ID to static methods in Flash, which then looks up the corresponding AS3 instance and dispatches events on it. This allows me to "reconnect();" without having to reattach event handlers, since the AS3 WebSocket just requests a new JS WebSocket and ID under the hood. – Triynko Aug 09 '13 at 05:17
  • 13
    When the server closes the connection, the client DOES NOT try to reconnect. With some JS frameworks maybe, but the question is tagged as plain Vanilla JS. – SzG Jun 30 '16 at 05:37
  • Indeed, having the client do a reconnect after a web socket was closed, needs to be programmed. It's not done automatically. See http://stackoverflow.com/questions/3780511/reconnection-of-client-when-server-reboots-in-websocket for some examples. – Jochem Schulenklopper Mar 17 '17 at 15:05
  • 3
    And there's a good reason for plain vanilla js not auto-reconnecting. Who wants to get his proxy hammered while the websocket server is down? Take your time and implement a reconnection strategy that suits your needs. – Daniel F Mar 22 '17 at 15:57
  • you di NOT answer the question! – Zibri Nov 16 '18 at 11:27
  • WebSocket never trying to reconnect – clarent Jan 14 '20 at 13:22
  • Should not be marked as the answer, please see @SzG answer for correct response. – jjxtra Apr 02 '20 at 16:01
0

Flawless implementation:

var socket;

const socketMessageListener = (event) => {
  console.log(event.data);
};

const socketOpenListener = (event) => {
  console.log('Connected');
  socket.send('hello');
};

const socketCloseListener = (event) => {
  if (socket) {
    console.error('Disconnected.');
  }
  socket = new WebSocket('ws://localhost:8080');
  socket.addEventListener('open', socketOpenListener);
  socket.addEventListener('message', socketMessageListener);
  socket.addEventListener('close', socketCloseListener);
};

socketCloseListener();

To test it:

setTimeout(()=>{
  socket.close();
},5000);

Edit: Take note of the Exponential Backoff implementation (at the linked thread by top comment: https://stackoverflow.com/a/37038217/8805423), not in above code BUT VERY VERY CRUCIAL.

Edit again: Check out back from primus: https://www.npmjs.com/package/back, it's a flexible sexy implementation.

xemasiv
  • 87
  • 3
  • 24
    I don't like the way you state it as "flawless implementation". Flawless for what? It's better to let others judge that by the votes. It is clever how you create the socket from within the close handler. Maybe that could be the introductory line, instead. – akauppi Jan 07 '18 at 00:20
  • @Pol answer is simpler and cleaner – jjxtra Apr 02 '20 at 16:02
-1

function wsConnection(url){
    var ws = new WebSocket(url);
    var s = (l)=>console.log(l);
 ws.onopen = m=>s(" CONNECTED")
    ws.onmessage = m=>s(" RECEIVED: "+JSON.parse(m.data))
    ws.onerror = e=>s(" ERROR")
    ws.onclose = e=>{
        s(" CONNECTION CLOSED");
        setTimeout((function() {
            var ws2 = new WebSocket(ws.url);
   ws2.onopen=ws.onopen;
            ws2.onmessage = ws.onmessage;
            ws2.onclose = ws.onclose;
            ws2.onerror = ws.onerror;
            ws = ws2
        }
        ).bind(this), 5000)
    }
    var f = m=>ws.send(JSON.stringify(m)) || "Sent: "+m;
    f.ping = ()=>ws.send(JSON.stringify("ping"));
    f.close = ()=>ws.close();
    return f
}

c=new wsConnection('wss://echo.websocket.org');
setTimeout(()=>c("Hello world...orld...orld..orld...d"),5000);
setTimeout(()=>c.close(),10000);
setTimeout(()=>c("I am still alive!"),20000);
<pre>
This code will create a websocket which will 
reconnect automatically after 5 seconds from disconnection.

An automatic disconnection is simulated after 10 seconds.
Zibri
  • 9,096
  • 3
  • 52
  • 44