socket.io: disconnect event isn't fired - node.js

I have made a simple realtime visitor counter.
You can download it from this repository.
What happens is that disconnect event (even after browser closing) on server is never fired.
server.js is:
(function () {
var app, count, express, io;
express = require('express');
io = require('socket.io');
app = module.exports = express.createServer();
app.configure(function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(require('stylus').middleware({
src: __dirname + '/public'
}));
app.use(app.router);
return app.use(express.static(__dirname + '/public'));
});
app.configure('development', function () {
return app.use(express.errorHandler({
dumpExceptions: true,
showStack: true
}));
});
app.configure('production', function () {
return app.use(express.errorHandler());
});
io = require('socket.io').listen(app);
count = 0;
io.sockets.on('connection', function (socket) {
count++;
io.sockets.emit('count', {
number: count
});
});
io.sockets.on('disconnect', function () {
console.log('DISCONNESSO!!! ');
count--;
io.sockets.emit('count', {
number: count
});
});
app.get('/', function (req, res) {
return res.render('index', {
title: 'node.js express socket.io counter'
});
});
if (!module.parent) {
app.listen(10927);
console.log("Express server listening on port %d", app.address().port);
}
}).call(this);
Script on the client is:
script(type='text/javascript')
var socket = io.connect();
socket.on('count', function (data) {
$('#count').html( data.number );
});

Put your on disconnect code inside your on connect block and edit it a bit like so:
io.sockets.on('connection', function (socket) {
count++;
io.sockets.emit('count', {
number: count
});
socket.on('disconnect', function () {
console.log('DISCONNESSO!!! ');
count--;
io.sockets.emit('count', {
number: count
});
});
});
This way you're detecting when a specific socket (specifically the socket you pass to your anonymous function that is run on connection) is disconnected.

From Socket.IO 1.0 the io.engine.clientsCount property is available. This property tells you how many open connection does your app currently have.
io.sockets.on('connection', function (socket) {
io.sockets.emit('count', {
number: io.engine.clientsCount
});
socket.once('disconnect', function () {
io.sockets.emit('count', {
number: io.engine.clientsCount
});
});
});
Note: Use .once instead of .on and the listener will be removed automatically from the socket what is good for us now, because the disconnect event is only fired once per socket.

Just in case anyone else made this silly mistake: make sure that any socket middleware you've defined calls next() at the end, or else no other socket handlers will run.
// make sure to call next() at the end or...
io.use(function (socket, next) {
console.log(socket.id, "connection middleware");
next(); // don't forget this!
});
// ...none of the following will run:
io.use(function (socket, next) {
console.log(socket.id, "second middleware");
next(); // don't forget this either!
});
io.on("connection", function (socket) {
console.log(socket.id, "connection event");
socket.once("disconnect", function () {
console.log(socket.id, "disconnected");
});
});

Related

Socket.io emit not working (by visiting URL)

I am developing an app that gets a signal from external hardware equipment. I catch this signal by redirecting it to a certain URL in my app: '/impulse/:id'.
I am able to catch the signal, but the emit function inside the app.get('/impulse/:id') is not triggering. The console logs are...
How can I make the emit function work?
Below is my server.js script, where I catch all the socket signals and prevent the external call from being redirected to the index page.
...
const express = require('express');
const app = express();
const port = process.env.PORT || 8080;
const socket = require('socket.io');
app.use(express.static(__dirname + '/public'));
app.use('/api', appRoutes);
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://HERE IS MY DB INFO...', function(err) {
if (err) {
console.log('Not connected to the database: ' + err); // Log to console if unable to connect to database
} else {
console.log('Successfully connected to MongoDB'); // Log to console if able to connect to database
}
});
var server = app.listen(port, function() {
console.log('Running the server on port ' + port); // Listen on configured port
});
var io = socket(server);
io.on('connection', function(socket){
socket.on('join', function(data){
var gameroom = data.gameid;
console.log("joined: " + gameroom)
socket.join(gameroom);
})
//FUNCTION I WANT TO TRIGGER
socket.on('impulse', function(data){
console.log('IMPULSE')
io.emit('impulseReceived', {
})
})
})
//PLACE WHERE I EMIT
app.get('/impulse/:id', function(req, res){
console.log('Impulse Received')
var time = req.query.TIME;
var gameroom = req.params.id;
io.on('connect', function (socket) {
socket.emit('impulse', {
})
})
res.json({ success: true, message: 'received the time!'})
})
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname + '/public/app/views/index.html')); // Set index.html as layout
});
Replace this whole
io.on('connect', function (socket) {
socket.emit('impulse', {
})
}
with this
io.emit('impulse', {})

In openshift Nodejs Socket.io responce 200 Ok, But console.log value not visible. my socket is working?

created index.js (server)
var express = require('express');
var app = express();
///creating server
var server = require('http').createServer(app);
var io = require('socket.io').listen(server, { origins:'http://nodejs-atnodejs.rhcloud.com:8000' });
below is remaining code
Routing to index.html page
app.get('/', function (req, res) {
console.log('in socket---' + res);
res.sendfile('index.html');
});
///socket connection
io.sockets.on('connection', function (socket) {
socket.on('chatmessage', function (msg) {
io.emit('chatmessage', msg);
console.log('in socket---' + data);
});
});
/// Listen to Openshift port
server.listen(process.env.OPENSHIFT_NODEJS_PORT, process.env.OPENSHIFT_NODEJS_IP);
created index.html(client)
src="http://nodejs-atnodejs.rhcloud.com:8000/socket.io/socket.io.js
var socket = io.connect('http://nodejs-atnodejs.rhcloud.com:8000');
console.log('this is index page');
socket.on('chatmessage', function (data) {
console.log('chatmessage---' + data);
socket.emit('chatmessage', { my: 'data' });
});
When accessed from browser:
Problem is not getting "console.log('chatmessage---' + data);" which is inside the socket..
and keep on getting xhr-polling../t=xxxxx responses..
is my socket working properly?
Both your browser and server code is listening for an event of 'chatmessage' after connection either your browser or server should be emitting the event first and than the other should be listening such as...
// server
io.sockets.on('connection', function (socket) {
socket.emit('chatmessage', /*some data*/);
});
//client
socket.on('chatmessage', function (data) {
console.log('chatmessage---' + data);
});

I'm unable to connect to socket

I'm trying to connect to a socket.But I did not get the socketid on the console.Is it the right way of connecting to a socket ?Can anyone please suggest me ...
My code :
var app = express();
var dir = process.cwd();
app.use(express.static(dir)); //app public directory
app.use(express.static(__dirname)); //module directory
var server =require('http').createServer(app);
var io = require('socket.io')(server);
io.of('/socket_issue').on('connection', function (socket) {
console.log("Socket connected :"+socket.id);
socket.emit('news', { hello: 'world' });
});
client code :
var socket = io('http://localhost:8085/socket_issue');
socket.on('connect', function(){ console.log('connected to socket'); });
socket.on('error', function(e){ console.log('error' + e); });
socket.on( 'news', function( data ){
console.log(data);
});
socket.on('disconnect', function(){});
You seem to not have a server.listen() in your backend code.
I've edited the server code and it functions correctly:
var app = require('express')();
var dir = process.cwd();
var server =require('http').createServer(app);
var io = require('socket.io')(server);
server.listen(8080);
app.get('/', function (req, res) {
res.sendfile(__dirname + '/index.html');
});
io.of('/socket_issue').on('connection', function (socket) {
console.log("Socket connected :"+socket.id);
socket.emit('news', { hello: 'world' });
});
Don't forget to change the port on the front-end and it'll work as expected:
Socket connected :Y7zi7dLRxqBA5nakAAAA

Socket Property Of Undefined

I am currently trying to make a real time chat room using node, express, and socket.io. When I run the code, I get this error message:
http://gyazo.com/d9956a80a691d1642b438173b0bd85bf
Also, here is my index.js code:
var express = require("express");
var app = express();
var port = 3700;
app.use(express.static(__dirname + "/public"));
app.set("views", __dirname + "/tpl");
app.set("view engine", "jade");
app.engine("jade", require("jade").__express);
app.get("/", function (req, res){
res.render("page");
});
io.sockets.on("connection", function (socket){
socket.emit("message", { message: "welcome to the chat" });
socket.on("send", function (data){
io.sockets.emit("message", data);
});
});
var io = require("socket.io").listen(app.listen(port));
console.log("Listening On Port " + port);
I have searched up over google and found no solutions that were related to my code. Please Help!
You are using the io variable before it's initialized move the var io before the io.sockets
var io = require("socket.io").listen(app.listen(port));
io.sockets.on("connection", function (socket){
socket.emit("message", { message: "welcome to the chat" });
socket.on("send", function (data){
io.sockets.emit("message", data);
});
});
You're using a variable before it's declared and your listen() calls look kind of strange.
Instead of doing this:
io.sockets.on("connection", function (socket){
socket.emit("message", { message: "welcome to the chat" });
socket.on("send", function (data){
io.sockets.emit("message", data);
});
});
var io = require("socket.io").listen(app.listen(port));
You should do something more like this:
var io = require("socket.io")(app);
io.sockets.on("connection", function (socket){
socket.emit("message", { message: "welcome to the chat" });
socket.on("send", function (data){
io.sockets.emit("message", data);
});
});
app.listen(port);
You are accessing the io variable before it is initialized.
Simply move the following line (io variable initialization):
var io = require("socket.io").listen(app.listen(port));
Before the first use of io variable at this line:
io.sockets.on("connection", function (socket){

duplicate message received on redis sub

I am using express 3x, node.js and redis. when i as publishing message then 1 have receive this message 2-3 times in subscribe. (e.g. when i am refreshing my browser, message receive increase by 1 each time) .
below is my code.
server side :
~~~~~~~~~~
var express = require('express'),
http = require('http')
var redis = require('redis');
var redisCli = redis.createClient();
var redisPub = redis.createClient();
var redisSub = redis.createClient();
redisCli.on("error", function (err) {
console.error("\r\n Error generated from redis client ", err);
});
redisPub.on("error", function (err) {
console.error("\r\n Error generated from redisPub ", err);
});
redisSub.on("error", function (err) {
console.error("\r\n Error generated from redisSub ", err);
});
var server = http.createServer(app)
, io = require('socket.io').listen(server);
server.listen(process.env.PORT);
app.configure(function () {
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.set('view options', { layout: false });
app.use(express.favicon(__dirname + '/favicon.ico', { maxAge: 2592000000 }));
app.use(express.bodyParser());
app.use(express.cookieParser());
app.use(express.session({ secret: "myKey", store: new RedisStore({ maxAge: 86400000, client: redisCli }), cookie: { maxAge: 86400000} }));
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + '/static'));
});
io.configure(function () {
io.enable('browser client minification'); // send minified client
io.enable('browser client etag'); // apply etag caching logic based on version number
io.enable('browser client gzip'); // gzip the file
io.set('log level', 1);
io.set("flash policy server", false);
io.set("transports", ["jsonp-polling", "xhr-polling"]);
});
io.sockets.on('connection', function (client) {
console.log("server - redisSub.subscribe from io.on.connection");
redisSub.unsubscribe();
redisSub.subscribe("announcement");
redisSub.on("message", function (channel, message) {
io.sockets.emit('announcement', message);
});
client.on('disconnect', function () {
redisSub.unsubscribe("announcement");
redisSub.quit();
});
});
app.post('/PublishMessage', function (req, res) {
redisPub.publish("announcement", req.body.users);
res.setHeader('Cache-Control', 'max-age=0, must-revalidate, no-cache, no-store');
res.setHeader('Connection', 'keep-alive');
res.contentType('application/json');
res.setHeader('Expires', new Date().addYears(-10));
res.json({ result: 'ok' });
});
Client side
~~~~~~~~~
this.socket = io.connect('http://XXX.XXX.X.XXX/', { transports: ['jsonp-polling', 'xhr-polling'] });
this.socket.on('connect', function () {
alert("client - Socket client connect");
});
this.socket.on('announcement', function (msg) {
alert("clientside - announcement ");
var nUsers = parseInt($('#Summary>article>p:last').text(), 10) + parseInt(msg, 10);
$('#Summary>article>p:last').text(nUsers);
});
=================================================================
So, any one guide me for the same !!!
thank you very much.
I have never used socket.io, but it looks to me like you're over complicating things with your connection handler.
Inside the handler, it doesn't seem like you're reacting to the connection (like emitting a "user connected" event) or modifying the behavior of the individual socket connection in any way.
What you are doing, is repeatedly subscribing and unsubscribing the one redisSub client. I could be wrong here, but I don't think you need to or should be doing that.
Rather you should sub "announcement" once, outside of the connection handler, as you don't need to sub/unsub this global client on every connection. Like:
// Move this subscription outside of the connection handler, and you shouldn't
// have to continue to sub/unsub or otherwise manage it.
redisSub.on("message", function (channel, message) {
io.sockets.emit('announcement', message);
});
// Since you're not reacting to connections or doing anything with individual
// connection sockets, you don't really have anything to do in this handler.
io.sockets.on('connection', function (socket) {
// if you ONLY wanted to emit to this socket, you'd do it here
//socket.emit("announcement", "just for this connection")
});

Resources