Express-generator, Socket.io Event issuing multiple times - javascript

I have create a node app using express generator. I have integrated socket.io in the application. Since express generator has their own way of creating express server i have followed this procedure to successfully integrate the Socket connection with listening server and made the io available throughout the application via res.io instance.
FILE: bin/www
#!/usr/bin/env node
var app = require('../app').app;
var debug = require('debug')('www:server');
var http = require('http');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);
/**
* Create HTTP server.
*/
var server = require('../app').server;
/app.js
//Express handler
var app = express();
// Socket configuration
var server = require('http').Server(app);
var io = require('socket.io')(server);
app.use(function(req, res, next){
res.io = io;
next();
});
...
module.exports = {app: app, server: server};
But the problem is when i m emitting an event as shown below. My client is reading the data multiple times.
routes/index.js
var clients = 0;
var nsp = res.io.of('/default-namespace');
nsp.on('connection', function (socket) {
clients++;
console.log(clients + ' clients connected!');
socket.on('disconnect', (reason) => {
clients--;
console.log(clients + ' clients connected!');
});
nsp.emit("socketToMe", "New User connected. Current clients:"+ clients);
});
My listener has the following code:
home.pug
var socket = io('/default-namespace');
socket.on('socketToMe', function (data) {
$('#data-div').append($('<li>').text(data));
});
Whenever i refresh the browser in another instance like incoginito my main browser is showing multiple events for the data. Like this
New User connected. Current clients:1
New User connected. Current clients:2
New User connected. Current clients:1
New User connected. Current clients:2
New User connected. Current clients:1
New User connected. Current clients:1
Not sure what is wrong. Can anyone help me on this?

Nodejs is event driven.The res object is not a global variable.
Express middleware runs for every request.
var clients = 0;
var nsp = res.io.of('/default-namespace');
nsp.on('connection', function (socket) {
clients++;
console.log(clients + ' clients connected!');
socket.on('disconnect', (reason) => {
clients--;
console.log(clients + ' clients connected!');
});
nsp.emit("socketToMe", "New User connected. Current
clients:"+clients);
});
Let me explain what happens above.A user requests and req handler is fired and you access the res object and you listen for events.
So for each request, you are listening for socket 'connection' event.That means you are setting multiple event listeners with the same name.Every time you make a request you set a new listener.
You are supposed to set only a single 'connection' listener.
This explains emitting the same event multiple times.
app.use(function(req, res, next){
res.io = io;
next();
});
Instead of using the above middleware function,listen directly on io instance

Related

Send messages from server to client socket.io

I am trying to send a message from NodeJS server to client using socket.io
However, I found the same practice all over the internet, which is wrapping the emit with io.on('connection', handler) and then making the server listen on a special "channel" event like so:
var io = require('socket.io')();
var socketioJwt = require('socketio-jwt');
var jwtSecret = require('./settings').jwtSecret;
var User = require('./models/users').User;
io.set('authorization', socketioJwt.authorize({
secret: jwtSecret,
handshake: true
}));
var sockets = [];
io.on('connection', function(socket) {
sockets.push(socket);
});
sendLiveUpdates = function(gameSession) {
console.log(sockets);
}
exports.sendLiveUpdates = sendLiveUpdates;
exports.io = io;
My problem is: I want to emit messages outside this on connection wrapper, example from my routes or other scripts. Is it possible?
Thanks.
Yes. You just need to keep a reference to the socket.
// Just an array for sockets... use whatever method you want to reference them
var sockets = [];
io.on('connection', function(socket) {
socket.on('event', function() {
io.emit('another_event', message);
});
// Add the new socket to the array, for messing with later
sockets.push(socket);
});
Then somewhere else in your code...
sockets[0].emit('someEvent');
What I usually do is assign new clients a UUID and add them to an object keyed by this UUID. This comes in handy for logging and what not as well, so I keep a consistent ID everywhere.

client code in node js

I am new to Nodejs and am trying to set up a server client connection using sockets. Below is my code. Server is working OK but client is not connecting.
Please can anyone help me figure out the mistake.
Much Thanks
jessi
Server.js
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
io.on('data', function(data) {
console.log('DATA from client is: ' + data);
// Close the client socket completely
});
server.listen(4200);
console.log('Monitoring server listening on port 4200');
Client.js
var HOST = '127.0.0.1';
var PORT = 4200;
var express = require('express');
var app = express();
var client = require('http').createServer(app);
var io = require('socket.io')(client);
client.connect(PORT, HOST, function()
{
console.log('CONNECTED TO: ' + HOST + ':' + PORT);
// Write a message to the socket as soon as the client is connected,
// the server will receive it as message from the client
io.write('I am Chuck Norris!');
});
// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function(data) {
console.log('DATA: ' + data);
// Close the client socket completely
client.destroy();
});
// Add a 'close' event handler for the client socket
client.on('close', function() {
console.log('Connection closed');
});
For the client you use the socket.io-client package instead. The client side doesn't require the use of the Express portion since you're not recreating a web server on the client. If you look at your current code you're essentially recreating the Socket server which isn't what you want to do.
All that is necessary is to create a new Socket.io client and register your various event handlers.
var socket = require('socket.io-client')('localhost:4200');
socket.on('data', function(data) {
// handle incoming data
console.log(data);
});

How can I have faye-websockets code running in the browser?

I'm new with node.js/express and all and I want to be able to notify any clients in browser about a new message received from some algorithm in the back-end. The publisher algorithm connect to the websocket and writes the message.
As far as I've looked there were examples which recommended websockets but I haven't been able to run that code in browser only in console.
Example client code:
var WebSocket = require('faye-websocket');
var ws = new WebSocket.Client('ws://localhost:1234');
var http = require('http');
var port = process.env.PORT || 1235;
var server = http.createServer()
.listen(port);
// receive a message from the server
ws.on('message', function(event) {
alert(JSON.parse(event.data));
});
Thank you
Found the answer after some trial/error iterations.
The algorithm now does a POST to an URL which in turn triggers a write to sockets for all connected clients via socket.io.
Client code:
var socket = io('http://localhost:7777');
socket.on('message', function (msg) {
document.body.insertAdjacentHTML( 'beforeend', '<div id="myID">'+msg+'</div>' );
});
And on the server, when client connects I retain it's socket into an array so I can write to each one:
Server code:
io.on('connection', function(socket){
console.log('a user connected: '+socket.id);
var id = clientCount++;
clientSockets[id] = socket;
socket.on('disconnect', function(){
console.log('user disconnected');
delete clientSockets[id];
socket = null
});
});
app.post('/alerts', function(req, res) {
req.accepts(['json', 'application']);
console.log("Algo did a POST on /alerts!");
// send the message to all clients
//console.log(req.body);
for(var i in clientSockets) {
clientSockets[i].send(JSON.stringify(req.body));
}
res.send(200);
});
In conclusion, I'm not using faye-websockets but instead socket.io

NodeJS Stop listening to a certain port

I want to 'reconnect' to a server with different values and I have this right now.
var server = http.createServer(function(req, res) {
if(url!="close"){
server.on("listening", function () { server.close(); });
var file = engine.files[indexOfMovie];
res.setHeader('Content-Length', file.length);
file.createReadStream().pipe(res);
}
});
server.listen('2020');
So what I need to do is let the listener which is already listening stop when a new server is defined and afterwards start the new server.
How can this be done in NodeJS?

How to host a socket.io server and a http server together?

I have a Socket.io server and a basic HTTP server that I coded together, but the problem is that the HTTP-server tries to serve requests that socket.io should serve.
Code:
//Dependences
var sio = require('socket.io');
var http = require("http");
var NewRequestHandler = require('./NewRequestHandler').Handler;
var DisconnectHandler = require('./DisconnectHandler').Handler;
var AuthorisationRequestHandler = require('./AuthorisationRequestHandler').Handler;
//The backlog of resources
var ResourceBackLog;
var ResourceRequestHandler = require("./ResourceRequestHandler").Handler;
//Reports the IP adress and Port that it will run on.
console.log('IP address: ' + process.env.IP);
console.log('Port: ' + process.env.PORT);
//Creates and configures a new http.server instance.
var Server = new http.Server();
//Starts both the http and socket.io server.
var io = sio.listen(Server.listen(process.env.PORT, process.env.IP, ResourceBackLog, function(error) {
if (error) {
console.log("Error: " + error);
} else if (!error) {
console.log("Server started sucsessfully.");
Server.on('request', ResourceRequestHandler);
console.log("Server now ready for requests.");
}
}));
//Handles the connect and authorisation bit
io.sockets.on('connection', function(socket) {
console.log('New Connection');
socket.on('auth', function(Keys) {
console.log('Autorisation Request Recived');
AuthorisationRequestHandler(socket, Keys, function() {
socket.on('NewRequest', function(Request) {
NewRequestHandler(socket, Request);
});
socket.on('diconnect', function() {
DisconnectHandler(socket);
});
});
});
});
The ResourceRequestHandler is the file that serves resources by checking the URL then opening the file at that location,
but it also serves /socket.io requests.
I would have Socket.io listen on another port and have the regular http server direct requests to it that way you can be sure they won't interfere with each other.
// create server
io = http.createServer();
io.on('uncaughtException', function(exception) {
console.log(exception);
});
io.listen(4001);
http.createServer(RequestHandler) and new http.Server(RequestHandler) work
Based on Socket.IO 0.9.6.
It is important to attach your custom request listener before the socket.io one. Socket.IO will then serve the requests it can and delegate all the others to your own request listener.
The algorithm in socket.io/lib/manger.js, is as follows.
In constructor:
1. remove all the existing request listeners.
2. attach Socket.IO request listener.
On request:
1. try to handle the request.
2. if Socket.IO cannot handle it, it delegates the request to the original listeners - those which were earlier removed in the constructor.

Categories

Resources