Socket io namespace server emit three times to client - node.js

Hi i have been looking through questions here on why my socket io server is emitting three times to the client.
DISCLAIMER: this is not a duplicate question, please view my issue carefully
This is how i bind the server to express
var server = http.createServer(app);
var io = require('socket.io').listen(server);
//var io = require('socket.io')(http);
require('./routes/sock')(io);
//server.listen(port);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
Now this is how i listen in my routes/sock file, i simply create a namespace and start listening for events
module.exports = function (io) {
var chat = io.of('/chat');
chat.on('connection', function (cs) {
console.log('User Connected to chat');
// save client id
var socketid = cs.id;
chat.setMaxListeners(0);
cs.on('my message', function (event) {
chat.to(socketid).emit('my message', 'for your eyes only');
});
cs.on('second message', function (event) {
chat.to(socketid).emit('second message', 'for your eyes only');
});
cs.on('third message', function (event) {
chat.to(socketid).emit('third message', 'for your eyes only');
});
.....
//other events follow with the same flow
})
}
Analysis
On the client side, i have logs and the client is emitting only once,
However when the server responds it emits three times to the client, making the client listener fire three times
What am i doing wrong?
This is not a duplicate question please, no one is having the same issues with namespaces.

Update, there wasn't anything wrong with my socket server, the problem was on my client side android, my client could listen more than once, it's in the android Activity lifecycle. Basically my android developer told me that he called the listener in the onResume and onPause which made it listen twice. Anyway am not an android developer, i just hope no one gets the same issue.

Related

Trigger `socket.io` event from server(`node.js`), not from client

I am trying to make a game server with node.js, socket.io.
The basic idea likes below.
Initialize socket.io instance when the server starts
Store instance in global scope, so controllers can access it
When API calls, we trigger some socket.io event in the controller or some other points
Here is the implementation I made ...
First, in server.js - entry point
let GlobalVars = require('./state/GlobalVars');
const apiRouters = require('./router');
...
app.use('/api', apiRouters);
app.get('/', (req, res) => {
res.sendFile(`${__dirname}/test/simpleClient.html`)
});
const httpServer = http.createServer(app);
let socketIOInstance = socketIO(httpServer);
socketIOInstance.on('connection', (socket) => {
console.log('SOCKET.IO A USER CONNECTED');
socket.on('create', (data) => {
console.log('SOCKET.IO create called', socket);
socket.join(data.room);
socketIOInstance.emit('message', 'New people joined');
});
socket.on('join', (data) => {
console.log('SOCKET.IO join called', data);
})
socket.emit('message', 'Hi');
});
GlobalVars.socketIO = socketIOInstance;
// Add to global, so the controllers can manage own actions like create, join ...
httpServer.listen(port, () => {
console.log(`Server Listening on the port ${port}`);
})
...
When I access from a client, I am able to see SOCKET.IO A USER CONNECTED and Hi in the browser console.
Second, In api controller.
let GlobalVars = require('../state/GlobalVars');
...
router.post('/create', (req, res) => {
console.log('GenerateGameSokect');
let game = new Game();
let gameId = game.gameId;
// console.log('Global vars ', GlobalVars.socketIO);
GlobalVars.socketIO.emit('create', {
room: gameId
});
res.json({
result : 'SUCCESS',
game : game
})
});
I imported GlobalVars which contains socketIO instance. So what I expected was, socket create event triggered from the statement GlobalVars.socketIO.emit('create', Object) but could not find message in the server logs.
I got no clue what I was missing.
The final form I pursue is something like...
When user call create API, I creates socket connection and room
API will called in HTTP protocol, but in the API, the server publishes some events. - pubsub like.
Thanks for reading my questions b. Here is full source code till now(bitbucket public)
================== EDIT ====================
I got understood (maybe...)
The user-flow I wanted was ...
The client call API
(In the server) Checking validation in API and if valid emit to socket.io
If event accepted send new status to all clients
However, creating socket.io connection in the server looks strange for me, the solution is up to the client.
New user-flow I will change
The client call a validation API
If return is valid, the client emit socket.io event. This time server only do validation, not emit socket.io
In socket event, send new status to all other users
================== EDIT #2 ====================
This is a kind of conclusion. It looks I just misunderstanding the concept of socket communication. Like answer and replies say, Socket and HTTP are totally different channels, there is no way to connect both. (At least, without open new connection from http server to socket)
If this is wrong, you could add reply, Thanks
Now I understand you. Or at least I think!
Let's put it this way: there are two (asymetric) sides on a socket, server and client. What I called, respectively, "global manager" and "socket" in my comment to your post.
const server = require('socket.io')(yourHttpServer);
// client is installed as well when `npm i socket.io`
const client = require('socket.io-client')('http://localhost:' + yourServerPort);
// `socket` is the server side of the socket
server.on('connection', (socket) => {
// this will be triggered by client sides emitting 'create'
socket.on('create', (data) => {
console.log('a client socket just fired a "create" event!');
});
});
// this will be triggered by server side emitting 'create'
client.on('create', (data) => {
server.emit('create', {content: 'this will result in an infinite loop of "create" events!'});
});
In your /create route, when you GlobalVars.socketIO.emit('create', ...), the server-side socket handler isn't triggered, however if you have clients connected through a browser (or, like I showed above, if you connect a client socket directly from the server) then these will trigger their 'create' listener, if any.
Hope this helps you get on the right tracks!

How to emit data from socket-IO client to socket-IO server?

so I am developing an small application that need a bi-directional channel to transmit data between client and server.
I have no problem to send sata from server to client. Works just fine. But , the other way around is not working. for some reason , sending data from client to client does not work.
here is the client.js
let io = require('socket.io-client');
let socket = io.connect("http://localhost:5000/", {
reconnection: false
});
socket.on('connect', function() {
console.log('Connected to server');
socket.emit('data', 'data is emitted !')
});
and here is server.js :
var io = require('socket.io').listen(process.env.port||5000);
io.on('connection',function () {
console.log('client connected');
io.on('data',function (data) {
console.log(`data received is '${data}'`)
})
});
What am I missing ?
The server code needs to listen for incoming events from a particular socket.on(), not io.on(). io is the server. It gets notified of new connections, but not of individual messages on a given connection. You have to listen to events on a particular socket to receive data from the client.
So, change to this (change io to socket in one place and add socket argument to the io.on('connection', function(socket) ()); handler (see the two places that socket was added below):
const io = require('socket.io').listen(process.env.port||5000);
io.on('connection', function(socket) {
console.log('client connected');
// listen for incoming data msg on this newly connected socket
socket.on('data',function (data) {
console.log(`data received is '${data}'`)
});
});
Note: the addition of socket in two places.

How to create multiple Nodejs socket io server-client?

I am new to Nodejs and Socket.io, and this is first time when I am creating any chat application, so pardon me if I am asking some silly question.
In my web I have to kind of chat services, one is Live debate which is kind of chat room, and another one is private messaging like Facebook Messenger.
I have created both, in private messenger before showing the message I am checking the conversation Id, it's working quite appropriately. Live debate is also working appropriately.
But there is a issue, any message sent in private messenger displays in live debate window also. So I change the Server.js file for messenger and also changed the listening port, now the listening port for live debate is 3000 and for messenger is 8050, but still Live debate receiving the messenger messages.
Am I doing this in wrong way? Is there any other way to run two chat applications ?
I am using this server code
var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var redis = require('redis');
server.listen(3000);
io.on('connection', function (socket) {
console.log("client connected");
var redisClient = redis.createClient();
redisClient.subscribe('message');
redisClient.on("message", function(channel, data) {
console.log("mew message add in queue "+ data+ " channel");
socket.emit(channel, data);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
With using Namespace
server.js
var nsp = io.of('/debate')
nsp.on('connection', function (socket) {
console.log("client connected"+socket.id);
var redisClient = redis.createClient();
redisClient.subscribe('message');
var redisClient1 = redis.createClient();
redisClient1.subscribe('debate');
redisClient.on("message", function(channel, data) {
console.log("mew message add in queue "+ data+ " channel");
nsp.emit(channel, data);
});
socket.on('disconnect', function() {
redisClient.quit();
});
});
client code
var socket = io.connect('http://localhost:3000/debate');
socket.on('message', function (data) {
data = jQuery.parseJSON(data);
console.log(data.user);
$( "#messages" ).append( "<strong>"+data.user+":</strong><p>"+data.message+"</p>" );
$('#messages').animate({
scrollTop: $('#messages').get(0).scrollHeight}, 200);
});
socket.io supports the use of different namespaces. You should use that feature instead of creating two individual servers. After that you can use socket.emit to that specific namespace. For more information see the documentation: https://socket.io/docs/rooms-and-namespaces/
It's not too difficult, I wrote a chat app, as I think everyone does when they start nodejs, but nodeJS has rooms which are quite easy to use.
io.on('connection', function(client){
client.on('room_connection', function(id){
client.join(id); // User joins room.
})
client.on('message', function(data){
io.to(data.room).emit('message', {message:data.message, client:client.conn.id});
});
})
This is pretty much all you need. This works for PM's since u simply won't allow multiple users to join this chatroom, and normal chatrooms which multiple users can join.

Using Socket.io, connections keep dropping

I'm using Socket.io to do some communication between a phone and a web page, and I'm having issues with the server constantly dropping connections. I've seen a lot of other people posting about Socket.io where their connections drop after being idle for about 5 minutes or so, but this is a connection that has constant information being emitted back and forth, and the longest I've been able to maintain a connection is about 30 seconds.
The server side code I'm running is:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
io.on('connection', function(socket){
socket.on('create', function (room) {
socket.join(room);
});
socket.on('player-move', function(msg){
roomId = msg['room'];
move = msg['action'];
socket.broadcast.to(roomId).emit('player-move', move);
});
socket.on('disconnect', function() {
console.log('someone has disconnected');
});
});
http.listen(443, function(){
console.log('listening on *:443');
});
The client side is pretty basic emit events. Here's an example:
$( "#arrow-left" ).on( "touchstart", function(){
var senddata = { "room": roomId, "action": "d-l" };
socket.emit( "player-move", senddata );
});
Everything seems to be running fine until 5-30 seconds after everything starts and then the connection just drops. The connection usually starts up again, but after 5-10 seconds. Has anyone had similar issue occurring? Would this potentially be an issue with the server rather than the code? I've done similar things before on different servers with Socket.io and haven't had this kind of connection issue. Any help or direction to go in would be appreciated. Thanks!
I had the same problem with another library called ws and I tried to handle the disconnection method properly by deleting the specific client sending the disconnection request from a array of clients. I don't exactly know how, but it solved my problem.
clients = []
io.on('connection', function(socket){
clients.push(socket);
// above methods
socket.on('disconnect', function(){
console.log("disconnected");
deleteFromArray(clients, socket.id);
});
});
function deleteFromArray(arr, element) {
position = arr.indexOf(element);
arr.splice(position, 1);
}

Node js - Socket.io-client is not connecting to socket.io server

I am trying to connect to a socket.io-client using the following code:
Server:
// Load requirements
var http = require('http'),
io = require('socket.io');
// Create server & socket
var server = http.createServer(function(req, res){
// Send HTML headers and message
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('<h1>Aw, snap! 404</h1>');
});
server.listen(8080);
io = io.listen(server);
// Add a connect listener
io.sockets.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
Client:
console.log('1');
// Connect to server
var io = require('socket.io-client')
var socket = io.connect('localhost:8080', {reconnect: true});
console.log('2');
// Add a connect listener
socket.on('connect', function(socket) {
console.log('Connected!');
});
console.log('3');
I don't get the Connected console log or Client Connected console log and I don't know why! The code sample is taken from another question posted: Link and I don't see any solution to the problem...
Use the same version of socket io client and server. It will work perfectly.
Also you need to add protocol with path.
change
var socket = io.connect('localhost:8080', {reconnect: true});
to
var socket = io.connect('http://localhost:8080', {reconnect: true});
Assuming you are using a socket.io version greater than 1.0, on the server, change this:
// Add a connect listener
io.sockets.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
to this:
// Add a connect listener
io.on('connection', function(socket) {
console.log('Client connected.');
// Disconnect listener
socket.on('disconnect', function() {
console.log('Client disconnected.');
});
});
See the socket.io documentation reference here.
You don't want to be listening for this event only on already connected sockets. You want to listen for this event on any socket, even a newly created one.
Also, be very careful when reading socket.io code in random places on the internet. Some things changed significantly from v0.9 to v1.0 (I don't know if this was one of those things or not). You should generally always start with the socket.io documentation site first since that will always represent the latest version. Then, if looking at other internet references, make sure you only use articles that are later than mid-2014. If you don't know the vintage of an article, it's best not to rely on it without corroboration from a more recent article.
you can use localhost. It works for me as well. You must use your ip address and port that works for you

Resources