20
votes

Socket.io for NodeJS doesn't seem to work as a websocket server

For some reason, socket.io ALWAYS fallback to the long polling and if I force the websocket transport layer, it will error out:

failed: Connection closed before receiving a handshake response

The right ports are open. I'm using the chat example from socket.io. I set up the server on http://jmi.io:3000. As you can see, it works fine with a beautiful long polling channel but now try the websocket connection from a websocket client and...

WebSocket connection to 'ws://jmi:3000/' failed: Connection closed before receiving a handshake response

I have only one node single threaded and have the exact same package.json than in the chat example repo.

{
  "name": "socket-chat-example",
  "version": "0.0.1",
  "description": "my first socket.io app",
  "dependencies": {
    "express": "4.3.1",
    "socket.io": "1.2.0"
  }
}

Thank you for your help

5
did you manage to solve this one?vlio20

5 Answers

30
votes

I had the exact same issue because I was defining 'io' twice. Double check where you are defining io in your code and ensure you are not defining the variable io twice.

Example of what I was doing wrong:

var server = require('http').createServer(app);
var io = require('socket.io')(server);

var io = require('socket.io').listen(server.listen(config.port, config.ip, function () {
    console.log('Express server listening on %d, in %s mode', config.port,     
    app.get('env'));
}));

Example of what fixed the issue:

var server = require('http').createServer(app);
var io = require('socket.io')(server);

server.listen(config.port, config.ip, function () {
    console.log('Express server listening on %d, in %s mode', config.port, 
    app.get('env'));
});
6
votes

Slightly related to what @Lucas Klaassen answered: I had the following:

let express = require('express');
let app = express();
let http = require('http').Server(app);
let io = require('socket.io')(http);
// this is the culprit:
app.listen(port);

Changing last line is what fixed it:

http.listen(port);
4
votes

In my case the problem was that I am proxying the server through browser-sync

browserSync({
    //server: {
    //  // src is included for use with sass source maps
    //  baseDir: ['public', 'src']
    //},
    proxy: "localhost:4045",
    port: 4046

So this will fail, however in production it works fine.

0
votes

Here is the complete working example from one of our working projects:

const websocket = require('ws');
const http = require('http');
const express = require('express');
const app = express();
const server = http.createServer(app);
wss = new websocket.Server({ server });
app.on('upgrade', wss.handleUpgrade);

wss.on('connection', ws => {
  console.log('web socket connection is alive');
}

server.listen(8080, () => {
    console.log('server started on PORT 8080');
});

translated from Medium

0
votes

It worked for me!

restUrl = 'http://x.x.x.x:5555;

socket = io(this.restUrl, {
        transports: ["websocket"],
        upgrade: true,
        upgradeTimeout: 6000000,
        pingTimeout: 15000000000,
        pingInterval: 1500000000,
        maxHttpBufferSize: 10000000,
      });

connect() {
        if (this.socket.connected == false) {
            var temp = this;
            this.socket.connect();
            this.socket.on('event', function (data) {
                temp.socketData.next(data);
            });
        }
    }