14

It seems to be taking about 1 second to set up a websocket connection when the client and server are both running locally on my machine. This seems like quite a long time to me - is it? Could anyone compare this with their own experiences?


Details:

I have a websocket request like this on the client (Chrome 25, Windows7 64):

this.ws = new WebSocket('ws://' + host + ':' + port);

On the server side I have Node with ExpressJS running and einaros/ws handling the upgrade and WS connection.

I'm timing on the client, from just before the new WebSocket() to the ws.onopen event.

UpTheCreek
  • 31,444
  • 34
  • 152
  • 221
  • Any reason you dont use Socket.io? – Jean-Philippe Leclerc Feb 28 '13 at 13:35
  • @Jean-PhilippeLeclerc Yeah I evaluated a few different libraries, ws fitted us better. As I understand it though, socket.io uses the ws library under the hood (it's listed as a dependency of socket.io in npm). Why, have you seen quicker setup times with socket.io? – UpTheCreek Feb 28 '13 at 13:48
  • Actually no. I already had this problem in one of my project using socketio. It was a little shitty test project so I didn't really cared. I don't have that problem in my new project tho. I'm still looking forward for the answer of your question. – Jean-Philippe Leclerc Feb 28 '13 at 15:56
  • 1
    Just out of curiosity, do you get the same results if you connect via IP address vs server name vs localhost? Wonder if the problem has to do with host name resolution. – Hector Correa Feb 28 '13 at 16:54
  • 2
    @HectorCorrea - aaah, looks like that might have been it. Just ran the test against 127.0.0.1 instead of localhost and it dropped from 1003ms to 3ms! Thank you! Now need to understand why that's happening (and test non-local again). – UpTheCreek Feb 28 '13 at 17:07
  • Hector or op might write an answer. – Jean-Philippe Leclerc Feb 28 '13 at 19:01
  • @Jean-PhilippeLeclerc - yes it was part of the problem but I'm still seeing about 500ms for the app now (using 127.0..), so I'm still investigating that. – UpTheCreek Mar 01 '13 at 06:28

2 Answers2

25

I found a clear answer to this question. Apparently, using localhost causes the browser to try to connect to ipv6 first then fallback to ipv4 after a 1 second timeout. The problem is solved by using 127.0.0.1 because it will try to connect using ipv4 in the first place.

Source

Jean-Philippe Leclerc
  • 6,713
  • 5
  • 43
  • 66
2

That is not normal.

I am using Chrome 24 on Ubuntu with the following test code (just fire up Chrome Dev console and paste it in):

function test_ws(uri){
    start = new Date().getTime(); 
    ws = new WebSocket(uri);
    ws.onopen = function(){
        console.log("onopen of", uri, "in", (new Date().getTime() - start), "ms");
    };
}

Here are some average results I've gotten for various values of uri:

  • ws://localhost:6080: 20 ms (custom python based WebSocket server)
  • ws://localhost:6090: 3 ms (custom node.js + einaros/ws based WebSocket server)
  • ws://echo.websocket.org: 130 ms
  • wss://echo.websocket.org: 190 ms

So even using an encrypted connection to a public remote Websocket server is still less than one fifth of a second on average until the open event. The maximum time I saw was 250ms. For a local connection, the delay should really only be a few milliseconds.

My guess would be that you server setup is doing a bunch of processing before accepting the connection. Perhaps you are initializing a bunch of client data in the new connection handler?

Update:

Here is a simple einaros/ws based WebSocket server that gives 3 ms onopen response using the client test code above:

var WebSocketServer = require('ws').Server
  , wss = new WebSocketServer({port: 6090});
wss.on('connection', function(ws) {
    console.log("got connection");
});
kanaka
  • 70,845
  • 23
  • 144
  • 140
  • Thank you for this answer - those times look more like I would have expected. I'm averaging about 1100ms at the moment, with the test set up pretty much identically to you. Interesting that the einaros/ws example is the fastest (which is the library I'm using). There is no explicit initialisation of client data going on - though I think I will check express middlewear next. Anyway this info has renewed my enthusiasm to get to the bottom of it! :) Cheers. – UpTheCreek Feb 28 '13 at 16:20
  • Interesting. Just ran your exact code - server and client (from dev console), result: `onopen of ws://localhost:6090 in 1003 ms`! I guess it wasn't express then. More investigation required... – UpTheCreek Feb 28 '13 at 17:02
  • HectorCorrea hit on something in the comments above - it seems that using 'localhost' instead of a loopback ip is introducing the delay. Don't know why yet, or why I'm seeing something similar on the server (need to double check!). Appreciate your help getting to the bottom of this! – UpTheCreek Feb 28 '13 at 17:08
  • Still not the end of the mystery though, as when I try the loopback address on the app I still have a delay of 500ms, which even with express middlewear seems long - will continue to investigate, and will post my findings. – UpTheCreek Feb 28 '13 at 17:22
  • Have stripped everything out, and still can't get below 200ms :/ – UpTheCreek Mar 14 '13 at 08:49
  • I had the same issue. ws connection from chrome to 127.0.0.1:8081 was taking more than 3 seconds; and moving from localhost to 127.0.0.1 on the javascript side didn't help earlier. My server was a self written c++ websocket server so I could see the precise 3+ sec delay when the accept() call would yield. Furthermore, a direct telnet from console to the ws server (localhost:8081) would yield immediately as one would expect. So there was definitely something that the browser was doing. Turned out, I had few chrome extensions installed. Disabling all of them brought down the delay considerably. – Neelabh Mam Oct 04 '19 at 13:16