Socket.io: Connection closed before receiving a handshake response - node.js

I decided to make a chat on socket.io, so I just copied an example from http://psitsmike.com/2011/09/node-js-and-socket-io-chat-tutorial/.
Server side:
var app = require('express').createServer()
var io = require('socket.io').listen(app);
app.listen(8080);
app.get('/', function(req, res) {
res.sendfile(__dirname + '/index.html');
});
var usernames = {};
io.sockets.on('connection', function(socket) {
socket.on('sendchat', function(data) {
io.sockets.emit('updatechat', socket.username, data);
});
socket.on('adduser', function(username) {
socket.username = username;
usernames[username] = username;
socket.emit('updatechat', 'SERVER', 'you have connected');
socket.broadcast.emit('updatechat', 'SERVER', username + ' has connected');
io.sockets.emit('updateusers', usernames);
});
socket.on('disconnect', function() {
delete usernames[socket.username];
io.sockets.emit('updateusers', usernames);
socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
});
});
Client side:
< script src="/socket.io/socket.io.js">< /script>
< script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></ script>
< script>
var socket = io.connect('http://localhost:8080');
...
The script works fine but I found out in the Chrome console that it can't establish a websocket connection, and falls back to XHR ('websocket connection invalid'). Tried to change ports, and also tested both on localhost and VPS - same results. What can be the reason? Using express 2.4.6 and socket.io 0.8.4.

Application is deployed as part of same container view , it will automatically connect using application url . Host and port might not be required , check with below options
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
</script>
Other option
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('http://localhost');
</script>

Related

unable to get data from socket.io-redis with nodejs

Hope you are doing well,
As I am creating a multiplayer games, so i need to store all user details from socket, after some time I need to make a group from the Users list.
So I tried to implement https://github.com/socketio/socket.io-redis library and trying to get all connected users but it's not working, I have developed according to this example Example to use socket.io-redis, but it'not work for me and my redis server is working well.
Thanks
Example :
index.js
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('socket.io-redis');
io.adapter(redis({ host: 'localhost', port: 6379 }));
var your_namespace_socket = io.of('/');
app.get('/', function(req, res) {
res.sendfile('index.html');
});
your_namespace_socket.on('connection', function(socket) {
console.log(socket.id);
socket.on('join', function(room) {
socket.join(room);
console.log(room);
//log other socket.io-id's in the room
your_namespace_socket.adapter.clients([room], (err, clients) => {
console.log(clients);
});
});
});
server.listen(3000, function() {
console.log('listening on *:3000');
});
index.html
<html>
<head>
<title>Hello world</title>
</head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io('/');
socket.emit('join', 'testingroom');
</script>
<body></body>
</html>
Output
User has joined session in a room with cannot fetch data from redis, as you can see in screenshot
Output of Above Code
I tested your code and it works for me, it might be an error with redis, do you have any error in the callback :
your_namespace_socket.adapter.clients([room], (err, clients) => {
if(err) console.log(err)
console.log(clients);
});

Chat application using socket.io not connecting when deploying on production server

I am trying to implement chat application using nodejs and socket.io. The application works on localhost. But when I deploy same on my production server then socket.io can't make any connection.
Code for server.js
var express = require('express');
var app = express();
var socket = require('socket.io');
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
var Group_controller = require('./controllers/GroupChatController.js');
app.get('/search', function (req, res) {
user_controller.get(req, res);
});
app.get('/groupSearch', function (req, res) {
user_controller.get(req, res);
});
var server = app.listen(3600, function () {
var host = server.address().address
var port = server.address().port
console.log("Example app listening at http://%s:%s", host, port)
});
var io = socket(server);
io.on('connection', (socket) => {
console.log('made socket connection', socket.id);
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
Group_controller.respond(io, socket);
user_controller.respond(io, socket);
});
io.on('disconnect', function () {
console.log('made socket disconnect', socket.id);
});
Code for client.js
var socket = io.connect('https://www.mywebsite.com', {
path: '/apichat'
});
/* Other events related to socket. */
As my server uses SSL I can't used IP:PORT directly so I am using ProxyPass as
ProxyPass /apichat http://127.0.0.1:3600
After all this still socket connection is not established between server and client.
Error shown in browser console is:
POST https://www.mywebsite.com/apichat/?EIO=3&transport=polling&t=MUc-TJK 404 (Not Found)
And in browser Network tab it shows:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
I have checked many other questions posted here and other sites but no question address this issue.
Please Help.
The issue you are encountering is probably due to ssl enabled on your website.
You need to pass ssl related files in your app.js file. Sample code for this is as follow:
var fs = require('fs');
var options = {
key: fs.readFileSync('PATH_TO_SSL_KEYS.key'),
cert: fs.readFileSync('PATH_TO_SSL_CERTS.crt'),
ca: fs.readFileSync('PATH_TO_SSL.pem')
};
var app = require('https').createServer(options, handler), io = require('socket.io').listen(app);
io.set('transports', [
'websocket',
'flashsocket',
'htmlfile',
'xhr-polling',
'jsonp-polling',
'polling'
]);
function handler(req, res) {
res.writeHead(200);
res.end("welcome sir!");
}
var chat_controller = require('./controllers/ChatController.js');
var user_controller = require('./controllers/UserController.js');
io.sockets.on('connection', function (socket) {
socket.broadcast.emit('userconnected');
chat_controller.respond(io, socket);
user_controller.respond(io, socket);
socket.on('message', function (data) {
socket.broadcast.emit('message', data);
});
});
io.on('disconnect', function (socket) {
console.log('made socket disconnect', socket.id);
});
app.listen(3300);
Try editing your application file as per above mentioned sample code and then try to use it. If you can't get path to ssl related file, then you need to contact either your system administrator or the hosting provider.
I hope it helped.

Socket.io makes connection on https://domain but doesnt make any on https://domain/route

Okay as I said i the title when I go to my home page the socket connection works perfectly but when I use a route it doesnt work at all here is my index.js
io.of('/admin').on('connection', function(socket) {
console.log('made socket connection', socket.id);
console.log(socket.request.user);
socket.on('chat', async function(data) {
console.log(data);
client.guilds.channels.get('474951005788962846').send(data);
io.sockets.emit('chat', data);
});
});
io.on('connection', function(socket) {
console.log('made socket connection', socket.id);
console.log(socket.request.user);
socket.on('chat', async function(data) {
console.log(data);
client.guilds.channels.get('474951005788962846').send(data);
io.sockets.emit('chat', data);
});
});
and on my /admin page here is my script that it is the same but the connection isnt as I added the /admin
<script>
var socket = io.connect('https://domain/admin');
// Query DOM
var serverID = document.getElementById('add_server_id');
var serverRoles = document.getElementById('add_role_ids');
var btnServer = document.getElementById('add_server_save');
//var output = document.getElementById('output');
// Emit events
btnServer.addEventListener('click', function(){
socket.emit('chat', {
serverid: serverID.value,
serverroles: serverRoles.value
});
});
//Listen for events
socket.on('chat', function(data) {
console.log(data);
//output.innerHTML += '<p><strong>' + data.game + '</strong></p>';
});
</script>
if someone can tell me why is it not connecting I would really appreciate it
var socket = io.connect('https://domain/admin');
to
var socket = io.connect('/admin');
The namespace is an implementation detail of the Socket.IO protocol,
and is not related to the actual URL of the underlying transport,
which defaults to /socket.io/….

How to clear redis database when nodejs server disconnect?

I have a simple chatroom application using a node express server.
This uses a redis database connection to store the nicknames of the joined clients.
I need to clear the redis SET of nicknames named members when the server is closed/disconnected.
This can be done as following:
redisClient.del("members", function(err, reply){
console.log("members set delete :" + reply);
});
But where should I put this code? How to handle the final event from the server when disconnection, from the server side?
Server code - chatroom.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var redis = require('redis');
var redisClient = redis.createClient();
io.on('connection', function(client){
console.log("client connected...");
});
io.on('connection', function(client){
client.on('join', function(name){
client.nickname = name;
//adding names
client.broadcast.emit("add member", name);
redisClient.smembers('members', function(err, names) {
names.forEach(function(name){
client.emit('add member', name);
});
});
client.emit('add member', client.nickname)
redisClient.sadd("members", name);
});
// remove clients on disconnect
client.on('disconnect', function(name){
client.broadcast.emit("remove member", client.nickname);
redisClient.srem("members", client.nickname);
});
});
app.get('/', function(req, res){
res.sendFile(__dirname + '/views/index.html');
});
server.listen(8080);
Client code - views/index.html
<html>
<head>
<title>Socket.io Client</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<h2>Chat box</h2><br>
<h4 id="status"></h4><br>
<div>
<h3>Active members</h3>
<ul id="members"></ul>
</div>
<script>
var socket = io.connect('http://localhost:8080');
socket.on('connect', function(data){
nickname = prompt("What is your nickname?");
$('#status').html('Connected to Chat Room as \''+nickname+'\'.');
socket.emit('join', nickname);
});
socket.on('add member', function(name) {
var member = $('<li>'+name+'</li>').data('name', name);
$('#members').append(member);
});
socket.on('remove member', function(name) {
$('#members li').filter(function() { return $.text([this]) === name; }).remove();
});
socket.on('disconnect', function(data){
$('#status').html('Chatroom Server Down!');
});
</script>
</body>
</html>
How to clear the redis database set when nodejs server disconnect?
you can use error or end events on redisclient, check the Redis Package Documentation
redisClient.on("error", function (err) {
console.log("Error " + err)
// delete here
});
However, since your connection is closed, it is more healthy to delete on first connection to redis each time. do it on reconnection state too.
When a socket.io connection dies, an event named disconnect is fired. Register your reset logic to that callback.
io.sockets.on('connection', function (socket) {
socket.on('disconnect', function () {
redisClient.del("members", function(err, reply){
console.log("members set delete :" + reply);
});
});
});
Credits : How can i handle Close event in Socket.io?

JS change socket namespace from client when click on button

I'm developping simple app with nodejs and socket.io.
I created two channels and I want my client connect one of channels when click on button. The problem is I don't get response from server
This is my code :
// SERVER side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendfile('MDC.html');
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
// CLIENT SIDE
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
console.log("setDay");
socket = io.connect('/day');
console.log(socket)
}
socket.on('hiDay',function(data){
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
function setWeek(){
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
}
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
});
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
In my client, I created two button and when I click on one I want change socket namespace
When you call setDay() or setWeek(), you are creating a whole new socket.io connection and thus overwriting your previous socket variable. The socket.on(hiDay, ...) and socket.on('hiWeek', ...) handlers you have are ONLY on the first socket you created, not on the newly created sockets, thus you never see the messages on those.
To fix, add those message handlers only to the right socket after you've connected to that namespace.
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
console.log(socket)
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
console.log(data)
});
}
Then, do the same thing for the setDay() function.
And, as shown here you probably want to disconnect the previous connection when changing namespaces too so you don't necessarily leave connections that you aren't using any more.
FYI, you also had a typo where this:
nameSpaceDay.emit('hiWeek', 'Hello everyone on namespace week!');
should have been this:
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
Final, tested and working code is this:
<!DOCTYPE html>
<html>
<head><title>Hello world</title></head>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
function setDay(){
socket.close();
console.log("setDay");
socket = io.connect('/day');
socket.on('hiDay',function(data){
console.log("hiDay")
document.getElementById('message-container').innerHTML = 'Update day';
console.log(data);
});
}
function setWeek() {
// close previous socket.io connection
socket.close();
// make new connection to new namespace
console.log("setWeek");
socket = io.connect('/week');
// add event handler for new socket
socket.on('hiWeek',function(data){
console.log("hiWeek");
document.getElementById('message-container').innerHTML = 'Update Week';
console.log(data);
});
}
</script>
<body>
<div id="message-container"></div>
<div id="error-container"></div>
<button type="button" name="button" onclick="setWeek()">Week</button>
<button type="button" name="button" onclick="setDay()">Day</button>
</body>
And server code:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var path = require('path');
var nameSpaceWeek = io.of('/week');
var nameSpaceDay = io.of('/day');
app.get('/', function(req, res){
res.sendFile(path.join(__dirname, 'socket-io-namespace.html'));
});
io.on('connection', function(socket){
console.log("User = " + socket.id)
});
nameSpaceDay.on('connection', function(socket){
console.log('someone connected on namespace day');
nameSpaceDay.emit('hiDay', 'Hello everyone on namespace day!');
});
nameSpaceWeek.on('connection', function(socket){
console.log('someone connected on namespace week');
nameSpaceWeek.emit('hiWeek', 'Hello everyone on namespace week!');
});
http.listen(3000, function(){
console.log('listening on localhost:3000');
});
If you create a connect(ns) function you can reconstruct the socket event listener when the namespace changes. The following should work:
<script>
var connect = function (ns) {
return io.connect(ns, {
query: 'ns=' + ns,
resource: "socket.io"
}).on('hiWeek', function (data) {
console.log("hiWeek")
document.getElementById('message-container').innerHTML = 'Update Week'
//document.getElementById('message-container').innerHTML = data
console.log(data)
}).on('hiDay', function (data) {
console.log("hiDay")
console.log("data = ." + data + ".")
document.getElementById('message-container').innerHTML = 'Update day'
console.log("data = ." + data + ".")
});
}
var socket = io();
function setDay() {
console.log("setDay");
socket = connect('/day');
console.log(socket);
}
function setWeek() {
console.log("setWeek");
socket = connect('/week');
console.log(socket);
}
</script>

Resources