Caroline Harrison
Caroline Harrison

Reputation: 178

Socket.io works with localhost but not on Heroku server

I am currently trying to use socket.io and a node.js server to communicate with a Unity script. I have everything hooked up and working with localhost, but for some reason when I port it to my Heroku server it can't connect. I'm assuming it might have something to do with the URL's? I'm new to socket.io so any help would be appreciated.

My node.js server:

var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
var path = require('path');

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

io.on('connection', function(socket) {
    socket.on('beep', function(){
        socket.emit("speed", {data: 5});
        console.log('beep recieved');
    });

    socket.on('change-speed', function(data) {
        console.log('change speed recieved: ' + data);
        socket.emit("speed", {newSpeed: data});
    });

    socket.on('ios-connection', function(data) {
        console.log('ios connection with message: ' + data);
    });

});

app.set('port', (process.env.PORT || 5000));

app.listen(app.get('port'), function() {
    console.log('Node app is running on port', app.get('port'));
});

My connection URL:

ws://<heroku app name>.herokuapp.com:5000/socket.io/?EIO=4&transport=websocket

Upvotes: 8

Views: 11545

Answers (6)

user1503606
user1503606

Reputation: 4300

Had a bit of a nightmare with this. Ended up reading through the docs.

Server: https://www.npmjs.com/package/socket.io Client: https://socket.io/docs/v4/client-initialization

It seems my structure was wrong see the docs.

In conjunction with Express

const app = require('express')();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
io.on('connection', () => { /* … */ });
server.listen(3000);

My full code.

const express = require('express')
const path = require('path');
const http = require('http')
const PORT = process.env.PORT || 5000
const app = express()
const server = http.createServer(app)
const cors = require("cors");

app.use(cors());

// Serve static files from the React app
app.use(express.static(path.join(__dirname, 'client/build')));

const io = require('socket.io')(server);
io.on("connection", (socket) => {

    
});

server.listen(PORT, () => console.log(`Server is running on port ${PORT}`));

And in my react code I am simply using.

const socket = io();

Hope this helps someone else

Upvotes: 0

Kiran Maniya
Kiran Maniya

Reputation: 9009

If you have deployed your application to Heroku, remove the port number from the URL of the server as given and it should work fine. ws://<heroku app name>.herokuapp.com/socket.io/?EIO=4&transport=websocket When you test the app locally, you can access the socket via http://localhost:YOUR_PORT_NUMBER wheres, after deployment, you don't need to specify the port.

Upvotes: 0

Orochii Zouveleki
Orochii Zouveleki

Reputation: 11

Ok, for some reason I tried everything on this question thread, and it worked. However not a single answer worked, but a combination of every one.

First, I removed the :PORT part in the URL, sort of like Chinnawat Sirima says. It is now...

ws://.herokuapp.com/socket.io/?EIO=4&transport=websocket

Then, for some reason initiating the server with this code from dangalg's answer/teyou's repo did work (I also noticed teyou's url doesn't have the port either).

var express = require('express');
var app = express();
var http = require('http').createServer(app);
var io = require('socket.io')(http);
var PORT = process.env.PORT || 3000;

(more code here)

http.listen(PORT,function(){
    console.log("Listening to port " + PORT);
});

Why do I say "for some reason"? Because I still don't know what I did lol. My guess is that I was setting the server in a way Heroku didn't like, but everyday localhost does. Because localhost doesn't care.

I'm just recompiling this because I've been in frustration with this problem for the last 8 hours, more or less. So I hope this helps someone else, to not lose valuable time and sleep.

(btw, I don't have a PORT variable in my Heroku, I have some other name, I guess that's another useless line but I'm not touching this anymore in case I break it again :D).

Upvotes: 1

Chinnawat Sirima
Chinnawat Sirima

Reputation: 410

I found the way!!. In Unity

if you run server in the localhost. the url should have " : port" example (port = 5000)

ws://127.0.0.1:5000/socket.io/?EIO=4&transport=websocket

but if you have deployed to **heroku the url must delete " : port"

ws://<heroku app name>.herokuapp.com/socket.io/?EIO=4&transport=websocket

It's work for me!

Upvotes: 6

duncanhall
duncanhall

Reputation: 11431

The problem is almost certainly an incorrect port number.

In your application, you are checking for process.env.PORT and if it is not set, you are defaulting to 5000.

In your ws URL however, you seem to be always expecting your application to be listening on port 5000.

You can check the config settings of your application by running the following command in the root of your project:

heroku run printenv

This will print a list of config vars, including the current set PORT value, eg:

PORT=9352

You should use this port when constructing your ws URLs, eg:

ws://your-app.herokuapp.com:9352/socket.io/?EIO=4&transport=websocket

Upvotes: 9

inampaki
inampaki

Reputation: 159

I have deployed your code with minor changes and its working fine on heroku please take a look into it. Server side app.js

var express = require('express');
var app = express();
app.set('port', (process.env.PORT || 5000));

var server = app.listen(app.get('port'), function() {
    console.log('Node app is running on port', app.get('port'));
});

var io = require('socket.io')(server);

app.use(express.static("./views"));

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "X-Requested-With");
  next();
});

app.get('/', function (req, res) {
    var path = __dirname + '/views/index.html';
    console.log(path);
    res.sendFile(path);
});

io.on('connection', function(socket) {
    socket.on('beep', function(){
        socket.emit("beep", {data: 5});
        console.log('beep recieved');
    });

    socket.on('change-speed', function(data) {
        console.log('change speed recieved: ' + data);
        socket.emit("speed", {newSpeed: data});
    });

    socket.on('ios-connection', function(data) {
        console.log('ios connection with message: ' + data);
    });
});

package.json

{
  "name": "socketio",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start" : "node app.js"
  },
  "author": "inampaki",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.3",
    "express-ws": "^0.2.6",
    "socket.io": "^1.3.7"
  }
}

index.html

<script src="/socket.io.js"></script>
<script>
  var socket = io.connect('/');
  socket.on('speed', function (data) {
    console.log('speed Message Received!');
    console.log(data);    
  });

  socket.on('beep', function (data) {
    console.log('beep Message Received!');    
    console.log(data);    
  });
  socket.emit("beep", {beep : true});
  socket.emit("change-speed", {"change-speed" : true});
  socket.emit("ios-connection", {"ios-connection" : true});


</script>

note that save index.html and socket.io.js in views folder. URL on which I have deployed it is socketip

Upvotes: 2

Related Questions