40

I'm trying to get a server set up with socket.io, with bad results.

I am mostly following this guide, although it's somewhat out of date: http://www.williammora.com/2013/03/nodejs-tutorial-building-chatroom-with.html

The problem comes with socket.io, I'm not sure if it's client or server side. It appears to be trying to continuously poll the server, but is getting 404's back. That sounds like socket.io isn't running, but it all looks okay to me. It may also have something to do with paths and having a "public" directory, but I don't really know.

127.0.0.1 - - [Thu, 17 Jul 2014 00:51:36 GMT] "GET /socket.io/?EIO=2&transport=polling&t=1405558296120-0 HTTP/1.1" 404 73 "http://localhost:8080/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4"
127.0.0.1 - - [Thu, 17 Jul 2014 00:51:37 GMT] "GET /socket.io/?EIO=2&transport=polling&t=1405558297181-1 HTTP/1.1" 404 73 "http://localhost:8080/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4"
127.0.0.1 - - [Thu, 17 Jul 2014 00:51:39 GMT] "GET /socket.io/?EIO=2&transport=polling&t=1405558299207-2 HTTP/1.1" 404 73 "http://localhost:8080/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.76.4 (KHTML, like Gecko) Version/7.0.4 Safari/537.76.4"

Server

var exec = require( "child_process" ).exec;
var path = require( "path" );
var morgan = require( "morgan" );
var bodyParser = require( "body-parser" );
var _ = require( "underscore" );
var express = require( "express" );
var app = express();
var http = require( "http" ).createServer( app );
var io = require( "socket.io" )( http );

app.set( "ipaddr", "127.0.0.1" );
app.set( "port", 8080 );

//support JSON, urlencoded, and multipart requests
app.use( bodyParser() );

//log the requests using morgan
app.use( morgan() );

//specify the Jade views folder
app.set( "views", __dirname + "/../views" );

//set the view engine to Jade
app.set( "view engine", "jade" );

//specify static content
app.use( express[ "static" ]( "public", __dirname + "/../public" ) ); //using map-access of static so jslint won't bitch

io.on( "connection", function( socket )
{
    console.log( "A user connected." );
});

Client

script( src="js/socket.io.js" )
var socket = io.connect( "http://localhost:8080" );

I got the client js file from: node_modules/socket.io/node_modules/socket.io-client/socket.io.js

That path doesn't match either what the tutorial I'm using says, or what socket.io says to use, so maybe that's the problem, but it looks like it's probably the correct file.

Any help here?

EDIT For additional information, here is my folder hierarchy:

Webserver/
    my_modules/
        server.js
    node_modules/
        body-parser/
        express/
        jade/
        morgan/
        socket.io/
        underscore/
    public/
        css/
        js/
            server.js
    views/
        index.jade
    index.js
    package.json

The server.js in the my_modules folder is where I start socket.io on the server side. The server.js in the js folder is the client code to connect from the website.

Eli
  • 4,724
  • 6
  • 40
  • 50
  • Are you using nginx (or other webserver) in front of node? if so, it looks like it doesn't proxy to node properly. – Oleg Jul 17 '14 at 17:33
  • Nope, just straight up node, with all the stuff I have listed in my requires (express etc). No nginx or apache. – Eli Jul 17 '14 at 18:31

4 Answers4

78

It looks like Socket.IO can't intercept requests starting with /socket.io/. This is because in your case the listener is app -- an Express handler. You have to make http be listener, so that Socket.IO will have access to request handling.

Try to replace

app.set( "ipaddr", "127.0.0.1" );
app.set( "port", 8080 );

with

http.listen(8080, "127.0.0.1");

See docs for details: http://socket.io/docs/#using-with-express-3/4

Oleg
  • 20,980
  • 9
  • 65
  • 83
  • 2
    You are the man! Thanks so much, that did the trick. I'll have to post a comment in the guide I was using. – Eli Jul 17 '14 at 19:13
  • 3
    Using http instead of app.listen ( in case of express ) fixed this for me, thank you. – Miguel Stevens Nov 03 '15 at 13:27
  • I have an express.Router used by app, and experienced the same problem. Letting http listen instead also solved my problem still keeping the app routing intact. Thanks a bunch @Curious! I did find the same page as you refer to, but somehow managed to overlook the solution! :D – hasse Jul 09 '16 at 07:04
  • Ohh, dear, you save my time, thanks a lot for your answer, I have tried to find solution for 2 days, thanks God I find your answer, Big + from me – Anna Gabrielyan Jun 08 '17 at 07:15
  • You're the best, you got me out of a big trouble – we_mor Apr 22 '20 at 12:48
7

In my case, I created my app with the Express application generator. To solve this problem, instead of edit the app.js file on the root folder of the project, I edited the file bin/www on the line after the server is defined:

/**
 * Create HTTP server.
 */

var server = http.createServer(app);
var io = require('socket.io')(server); // Add this here

Update

I found a better way here Express Generator and Socket.io

Camilo
  • 2,774
  • 2
  • 27
  • 43
3

Just for check that is your server or just client problem you could use this web: websocket-echo, if this client connect right to your server (the first form client is usefull if your server is online, if is on your host, cuoting from websocket.org...

Using a text editor, copy the following code and save it as websocket.html somewhere on your hard drive

Code: websocket-test

The only thing different from mine that i could observe is the io client source: <script src="/socket.io/socket.io.js"></script> on your client side.

On your server you should try this way:

var express = require('express'), 
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server),
exec = require('child_process').exec,
util = require('util');

//serve our code
app.use(express.static('public'));
app.use(express.json());
app.use(express.urlencoded());
//listening on connections

io.on('connection', function (socket) {
    console.log('client connected!'); 
}
server.listen(8080);

Note that this way works fine with this dependencies: I recommend you add this code below to your package.json file:

"dependencies": {
    "express": "3.x.x",
    "socket.io": "*",
    "util": "*"
  }

cheers!

  • Doesn't look like your code helps, and also you have an older version of express (json is no longer a dependency in my version and must be installed separately). How do I use websocket-echo? I tried putting in ws://localhost:8080 as the URL and it doesn't seem to connect. – Eli Jul 17 '14 at 18:44
  • Also when I try to use /socket.io/socket.io.js as the URL for the client code, I get a 404. My folder hierarchy is now edited into my post above. – Eli Jul 17 '14 at 18:46
  • 1
    yes, sorry about websocket-echo, seems to be useless if you are trying to reach a server running on your host, instead you should try your own test like this: [link] http://pastebin.com/NW3dWb2c ( property of www.websocket.org ), sorry if json line confuses you..is from my project :P . In order to use socket.io (client) you have to find where is installed your socket.io folder (generally on node-modules), in your case, i think that you need to put: /socket.io/socket.io.js . Again sorry if my code doesn't helped you. – lgargantini Jul 19 '14 at 21:13
0

Re-posting this answer here, as no other answer worked for me and this one did the trick. It took me a while to find it, so hopefully I'm saving some of you time.

import io from 'socket.io-client'

const socket = io('http://localhost:3000', {
    reconnectionDelay: 1000,
    reconnection: true,
    reconnectionAttemps: 10,
    transports: ['websocket'],
    agent: false,
    upgrade: false,
    rejectUnauthorized: false
});
halfer
  • 19,471
  • 17
  • 87
  • 173
Luigi
  • 146
  • 1
  • 5
  • In general if an answer on a thread suffices to answer a different question, the questions can be marked as a duplicate. Is that the case here, would you say? – halfer Sep 08 '21 at 16:36
  • @halfer I wouldn't say so, but just because I don't think this answer answers this question (or the other question) directly. The accepted answer for both questions didn't solve my problem, but this answer did. Put another way: there might not be an SO question for this answer, but people with that question might show up here. – Luigi Sep 09 '21 at 01:09
  • @halfer side note, beginner question: what is the reason to trim out voting advice? It was an effort to not 'steal' upvotes, but perhaps I missed some convention? – Luigi Sep 09 '21 at 01:12
  • 1
    On the side note, I'd give two suggestions: (1) that succinct technical writing is preferred, and (2) that voting should be allowed to be organic. I doubt that people vote based on advice anyway - where people ask for upvotes for themselves it is either routinely ignored, or they get a downvote. – halfer Sep 09 '21 at 06:56