Error: http://localhost:3001/socket.io/ 404 (Not Found) - node.js

I am trying to connect client-server using socket.io however at the moment of testing my code I am getting this error http://localhost:3001/socket.io/?EIO=3&transport=polling&t=MgUqscg 404 (Not Found)
I already tried two different ways to achieve this. One returns the error already specified the second one returns an error listen EADDRINUSE :::3001
can somebody please explain to me what am I doing wrong? all tutorials seem so easy but I am stuck at this point and I really want to learn how to use sockets to improve my skills.
This is my code for server
const express = require('express');
const http = require('http');
const app = express();
// Web socket config option #1
var server = http.Server(app);
var io = require('socket.io')(server);
// Web socket config option #2
var io = require('socket.io').listen(server);
server.listen(PORT)
const PORT = process.env.PORT || 3001;
app.set('port', 3000)
io.on('connection', (socket) =>{
console.log('a user is connected')
})
app.listen(PORT, function(){
console.log(' ======= SERVER RUNNING =======');
})
This is my code for client
import * as io from 'socket.io-client';
private socket = io(`http://localhost:3001`)
I just want to connect client-server successfully without errors and print to console a success message. Thanks in advance.

two thing from my experience.
remove app.listen official doc
upgrade problem official doc
cheers,
hope it can help you

I solved it by using a different port for sending secket.io events.
server.listen(4444)

Related

Websocket connection error : Does not return a 101 changing protocal when using from different path

I am using easy-rtc with socket.io for multiuser experience in my metaverse project. We maintain the connection in socket.io using polling and web-socket. I am facing problem in web-socket connection when I am trying to give path to the socket.io.
Firstly, I am putting forward the code where I am not using any path.
You can get the complete code from here. https://github.com/networked-aframe/networked-aframe/blob/master/server/easyrtc-server.js
The web-socket connection request which I am getting from this code is giving me a 101 changing protocols as expected.
I am even getting the response for the web-socket request as connecting in the Postman.
Now, My backend is working at localhost:3333/api/ . I am trying to change the path of socket.io in the client and server as shown in the images below. but I am not getting the 101 changing protocol response from web-socket connection request. This is the code after path change.
This is the client side code:
This is the backend code :
This is the response which I am getting when running the code after doing the path changes.
When I am trying to hit the web-socket request in the postman also I am not getting any connection. One observation I have made is that in the request URL, it is not taking the localhost:3333/api/ path. (If this is the issue, suggest any work arounds for this.)
Without getting the web-socket connection, the server is not efficient for communication.
Anyone suggest working solutions for this.
I was able to reproduce it.
A working solution
The problem is in your server code. You are doing something like this:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const io = require('socket.io')(server, {path: '/api/socket.io'}) // here you are already attaching the socket.io server to the HTTP server
const socketServer = io.listen(server) // this line is not required!
The last line is not required. It should be used only with socket server istances not yet attached to any http server. In the previous line you are already importing the socket.io main function, calling it, attaching to the HTTP server.
Therefore, try removing the .listen call and you will receive the 101 changing protocol http status code again.
With the above proposed solution, you can listen on socket events directly using the io istance. Like this:
io.on('connection', (socket) => {
console.log('a user connected');
});
Why it was working without the path?
Well, the first code snipped you provided should not work at all. From what I can see you were doing this:
const socketIo = require('socket.io')
socketIo.listen(webServer, {"log level": 1})
The above code can't work. The socketIo variable is an anonymous function. The listen method is not defined. Are you sure you have not initialized the module in a different way? Maybe are you using and old version of socket.io?
A better approach
Anyway, I suggest the new fresh, clean syntax socket.io documentation suggests;
Backend:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server, {path: '/api/socket.io'});
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', (socket) => {
console.log('a user connected');
});
server.listen(3000, () => {
console.log('listening on *:3000');
});
Client (I'm using a CDN but you could rely to your server for the socket.io-client code):
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="module">
import { io } from "https://cdn.socket.io/4.4.1/socket.io.esm.min.js";
const socket = io({path: "/api/socket.io"});
</script>
</body>
</html>

Socket.io is not connecting on Heroku

I am using Socket.io in my NodeJS backend. However, the sockets do not work. For example, one should receive a link and then send them to all other rooms under the same code, but the code is not executing. In my heroku logs I receive no errors but when I inspect element the page I get
polling-xhr.js:268 GET https://localhost:5000/socket.io/?EIO=3&transport=polling&t=NDADDNH net::ERR_CONNECTION_REFUSED
and
Failed to load resource: net::ERR_CONNECTION_REFUSED
I have looked into similar problems from this forum and made several changes but none of them have solved the issue. Also a bunch of the posts answer with solutions for ws in general which I don't understand at all :/
From what I read the issue might be with my ports? I followed a few of them but the same errors still occured.
Socket.io:
/***BACKEND***/
const express = require('express');
const path = require('path');
const app = express();
let rooms = [];
/***SERVER***/
const port = process.env.PORT || 5000;
server = app.listen(port, function(){
console.log('App is listening on port ' + port)
});
/***SOCKET.IO***/
const socket = require('socket.io');
io = socket(server);
io.on('connection', (socket) => {
//bunch of functionality
}
and then in my client I am using
this.socket = io('localhost:5000');
//one of the functions
this.syncQueue = () => {
this.socket.emit('SYNC_QUEUE', {
activeRoom: this.props.getRoom()
});
}
this.socket.on('RECEIVE_QUEUE', newQueue => {
props.onAddToQueue(newQueue);
});
FYI Everything works on localhost
Localhost will not work on the server and if you are using default namespace you no need to specify the URL. So try this, this.socket = io()
On the client side, you're trying to connect to localhost:5000 instead of the URL Heroku provides. Try this this.socket = io('heroku url goes here').

Issues with Socket.IO with Chrome and Firefox

Another update:
The problem occurs when running on localhost as well. Since I figured out the problem comes from the proxy server, here's its code :
var serverBouncer = bouncy(function(req, res, bounce) {
var path = req.url;
var url = req.headers.host;
if (typeof url !== "string")
return;
var urlArray = url.split('.');
var bouncePort = port;
if (!isNaN(urlArray[0]))
bouncePort = parseInt(urlArray[0]);
else if (String(urlArray[0]).toLowerCase() === "www" && !isNaN(urlArray[1]))
bouncePort = parseInt(urlArray[1]);
bounce(bouncePort);
});
serverBouncer.listen(80);
Update:
I found where the problem came from!!! But I still need to find the solution... There seems to be issues with using newer versions of Socket.io (>= 1.0) with a proxy server (bouncy, in my case).
I recently updated Socket.IO from v0.9.16 to v1.4.5, as well as adding Express to the mix. However, now I cannot open multiple (number seems to vary) tabs in Chrome and Firefox without experiencing strange issues (Edge is the only one to work well). It either hangs, or partially loads html and other resources before it hangs.
After waiting, I often get the error :
Failed to load resource: the server responded with a status of 400 (Bad Request)
When I close one of the tab that's been hanging, it unblocks the other tabs that were also hanging.
The issues were not present before going through with the changes listed above.
I've been doing research for 2 full days and just now decided to post this, as I know it's very vague and I'm probably not providing enough information. As much as I'd like to, it would take a very long time to remember and list everything I tried during that time.
Using Windows 10 with Chrome v51.0.2704.103, Firefox v43.0.1. The server (CentOS) is using node v6.2.2 with mainly the following modules :
express#4.14.0
npm#3.9.5
socket.io#1.4.5
Here's some relevant server code :
var port = 8502;
var socketio = require('socket.io');
var express = require("express");
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
server.listen(port);
app.get('/', function(req, res, next) {
//Returning index.html
});
io.on("connection", function(socket) {
//Some events...
});
Here's a bit of the client code :
var client = io.connect();
client.on('connect', function() {
//Some events
})
your binding before the server is listening, try something like this
var app = express();
server = app.listen(PORT, function () {
console.log('Example app listening on port ' + PORT + '!');
});
io.listen(server);
I managed to replace the bouncy module with nginx. See my other question for the solution.
nginx : redirect to port according to domain prefix (dynamically)

How to Properly Use Socket.IO in Node.JS for Use in Routes / with Heroku?

Please excuse any noobiness, I'm learning. :)
I have Socket.IO set up so that I can use io.sockets.emit inside of my routes, and I have that working. There are a few problems.
(SOLVED? SEE EDIT 3) To use, I cannot start with the word socket. I have to start with ioor I get "ReferenceError: socket is not defined." I'd like to be able to use socket.broadcast.emit to emit the event to all clients except for the current user. Right now I'm having to do a check on the client side to not execute the event if it's the current user and it's becoming a real headache as I'm having to emit more events as my project progresses.
(SOLVED, SEE EDIT 1 & 2) I have to run the application with node app.js and restart the server manually every time I make a server-side change. When I run nodemon, I get "Port 3000 is already in use." I feel that this must be related to the following...
(SOLVED, SEE EDIT 2) When pushing to Heroku, I have the port from the code below changed from 3000 to 80 in bin/www and app.js, but it does not work (I can see a 404 error for sockets in the console). If this and #2 are caused by dealing with http/ports in both places, how do I properly set this up and why does node app.js work?
I only need to run Socket.IO on the route shown below (battlefield). Am I already doing this with am I already doing this with require('./routes/battlefield')(io)?
bin/www
var app = require('../app');
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
var server = http.createServer(app);
server.listen(port);
app.js
var app = express();
var http = require('http').Server(app);
http.listen(3000);
var io = require('socket.io')(http);
app.set('socketio', io);
var battlefield = require('./routes/battlefield')(io);
battlefield.js
var express = require('express');
var router = express.Router();
var returnRouter = function(io) {
router.get('/', function(req, res, next) {
// other stuff
io.sockets.emit('message', 'This works');
socket.broadcast.emit('message', 'Socket is undefined');
})
return router;
};
module.exports = returnRouter;
I tried wrapping my routes in io.on('connection', function (socket) { to be able to use socket, and instead of 'Socket is undefined,' the event does not occur.
var returnRouter = function(io) {
io.on('connection', function (socket) {
router.get('/', function(req, res, next) {
// other stuff
socket.emit('message', 'This is never emitted');
})
})
return router;
};
I apologize for such a lengthy question. THANK YOU for any help! 💜
EDIT1: Writing out this question helped me understand the problem better. I commented out server.listen(port); in my bin/www and nodemon now works. However, the app crashes on Heroku. My Procfile is web: node ./bin/www... does that need to be changed?
EDIT2: After figuring out Edit1 and a bit of Googling, I found that I can't have server.listen(); (bin/www) and http.listen(3000); (app.js).
In bin/www, I removed server.listen();.
In app.js, for clarity's sake I changed var http = ... to var server = ... and had it listen for process.env.PORT || '3000';, taken from bin/www. I also removed app.set('socketio', io); because it looks like that was doing nothing... I wonder why it was in there.
app.js
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var port = process.env.PORT || '3000';
server.listen(port);
This also makes Heroku work because of process.env.PORT, hurray! I'm guessing node app.js worked because I was initializing the app with app.js, I guess bin/www is not executed when you do that?
I still need help with #1 (using socket.broadcast.emit) 😇.
EDIT 3: Well, it took me literally the entire day but I believe I have it figured out with one quirk. Of course I couldn't use socket, it is a parameter given on connect. I also need to access socket across different routes and found this SO question. This is what I ended up doing in battlefield.js:
var returnRouter = function(io) {
var socket;
router.get('/', authenticatedUser, function(req, res, next) {
io.on('connection', function(client){
socket = client;
});
// other stuff
res.render('battlefield', {/* data */});
setTimeout(function(){socket.emit('test', 'It works!')}, 500);
});
router.post('/', function(req, res, next) {
// socket can be accessed
});
return router;
};
module.exports = returnRouter;
(Note: I took out a lot of my own code so I don't know if this is copy and pasteable ready, and you should probably check that socket is not null)
Without setTimeout, socket is undefined on GET '/'. To my understanding, the page must render first... Strange that 200 sometimes doesn't work for me and 500 does. I can leave it at 500, but this is for a game so time is pretty important.
My questions now are:
Can this be improved / is there a way I can do this without setTimeout? Am I 'connecting' clients properly with this code and am I (question #4 up there^) using Socket.IO efficiently?
P.S. If no one answers ^ these questions, I'll edit this, answer the question, and accept my answer as best answer.
When you use sockets when doing routing in Node its not that useful.
When ever you navigate to a different name space (eg www.example.com --> www.example.com/some-name-space) your front end variables are deleted and you need to resend them. This works great if you pass an object along with the GET request for that name space. But it doesn't need sockets.
Its done like this on your router file
var canAlsoBePassed = {some: "things"};
router.get('/', function(req, res, next) {
res.render('index', { items: "Can be passed directly", variables: canAlsoBePassed });
});
For sockets the best kind of applications are for single page apps or to replace AJAX requests. Another great thing sockets allows is for the server to be able to push information without the client asking for it.
To answer your question about SetTimeout, no you dont need this.
Make sure the socket script running on your client side is waiting for the document to be loaded.
$(document).ready(function() {
When an io.on('connection' event fires on your server side you know you have a new client to serve.
emit an event from the server side something like a welcome event that makes the client join a specific room. Once you have them in that room you can be listening for any events emitted to that room.
See socket.io official info
Custom namespaces
To set up a custom namespace, you can call the of function on the server-side:
var nsp = io.of('/my-namespace');
nsp.on('connection', function(socket){
console.log('someone connected'):
});
nsp.emit('hi', 'everyone!');
On the client side, you tell Socket.IO client to connect to that namespace:
var socket = io('/my-namespace');
Might not be the most accurate answer to your questions but I hope it pushes you in the right direction.

Why does socket.io require a new listener

I know this ia probably a stupid question, but i sure hope i get the noob pass but I'm using the express framework with node js and mongo db. Why do you always have to create a new server in order for you to connect it from the client side.
1. server side:
var app = express();
var server = http.createServer(app);
var io = require('socket.io').listen(server);
server.listen(8000);
2. Client side:
var socket = io.connect('`http://localhost:8000`');
socket.on('connect', function () {
socket.emit('set nickname', confirm('Connected'));
});
Normally i would use localhost:/3000 now in order for me to connect to the server i have to use localhost:/8000 isnt there a way to use the default 3000 but this always throw an err:
events.js:72
throw er;
Regards
p.s i am very new to this and i am also reading tutorials but i cant seem to understand why this is please someone explain!
Do you require somewhere in your code http, express ?
Maybe another app running on :8000 ?
Also, maybe missing some listeners:
io.on('connection', function (socket) {
console.log('a user connected');
socket.emit('connect');
});

Resources