Send a message in socket.io-client - javascript

I have a direct question: can use in socket.io-client a method like in socket.io io.sockets.emit() to broadcast messages?
Here is my code and what a want to do:
var ioc = require('socket.io-client');
var s = ioc.connect("http://localhost:8000/", {reconnection: true});
s.on('connect', function () {
//...
}
//I want here out side of the <connect event> to send a message with socket.io-client

So thanks guys, the problem on from anothor place, I fixed it on my own like a man.
var ioc = require('socket.io-client');
var s = ioc.connect("http://localhost:8000/", {reconnection: true});
s.on('connect', function () {
...........
}
s.emit('msg','message')

Related

Why does this loop break my code?

Fair warning, I am a novice with javascript and ool. I am trying to put together a simple script to parse data out to a web socket. The script should be able to handle an infinite number of payloads.
This code works, although can only handle on payload at a time:
#!/usr/bin/env node
var io = require('socket.io-client');
var i=1
socket = io.connect('http://10.0.9.1:80');
var data = JSON.parse(process.argv[2]);
socket.on('connect', function(){
console.log('Emitting');
socket.emit('widget', data);
process.exit(0);
});
Wrapping the code in a loop with a logic test breaks it. No syntax errors, but it does not seem to call the emit method.
#!/usr/bin/env node
var io = require('socket.io-client');
var i=1
var data
while (true) {
i++
if ( process.argv[i] ) {
socket = io.connect('http://10.0.9.1:80');
data = JSON.parse(process.argv[2]);
socket.on('connect', function(){
console.log('Emitting');
socket.emit('widget', data);
});
} else {
process.exit(0);
};
};
The sockets you are creating are async, so you end up creating a bunch of sockets and then call process.exit(0) before there's time to establish the connection
There were many mistakes in my first attempt. Clues from ControlAltDel and mrid made me realize my loop structure was all wrong. The loop should have been placed within the on('connect') like so:
#!/usr/bin/env node
var io = require('socket.io-client');
var i=1
var data
socket = io.connect('http://10.0.9.1:80');
socket.on('connect', function(){
while (true) {
i++;
if ( process.argv[i] ) {
data = JSON.parse(process.argv[i]);
console.log('Emitting ');
socket.emit('widget', data);
} else {
process.exit(0);
};
}
});

Keep track of connected sockets with socket.io

How do I keep track of all the connected clients in socket.io?
I have tried this on the server:
let numSockets = 0;
io.on('connection', (socket) => {
io.sockets.emit('numSockets', ++numSockets);
socket.on('disconnect', () => {
io.sockets.emit('numSockets', --numSockets);
});
});
and this on the client:
const socket = io();
socket.on('numSockets', function (numSockets) {
console.log(numSockets);
});
It does print a number, but the number, however, if I open 2 windows, it shows 4 connected sockets.
Is this the correct way to do it?
What I want to achieve is to print a list of the connected sockets' ids in a sidebar on my website, and let the user set a username (instead of the automatically generated id) if they want to.
But before moving on to this, I will make sure I can keep track of the sockets in a correct way.
I don't think that io.sockets.emit(io.of('/').connected) is a good idea because it will send a hash of socket objects which is a lot of data :-)
You can try the following function:
function findUsersConnected(room, namespace) {
var names = [];
var ns = io.of(namespace || "/");
if (ns) {
for (var id in ns.connected) {
if(room) {
var roomKeys = Object.keys(ns.connected[id].rooms);
for(var i in roomKeys) {
if(roomKeys[i] == room) {
if (ns.connected[id].username) {
names.push(ns.connected[id].username);
} else {
names.push(ns.connected[id].id);
}
}
}
} else {
if (ns.connected[id].username) {
names.push(ns.connected[id].username);
} else {
names.push(ns.connected[id].id);
}
}
}
}
return names.sort();
}
which returns an array of users connected to a room in a namespace. If a socket has not socket.username property then socket.id is used instead.
For instance:
var usersConnected = findUsersConnected();
var usersConnected = findUsersConnected('myRoom');
var usersConnected = findUsersConnected('myRoom', '/myNamespace');
There's the Namespace#connected object that contains all sockets (keyed by their id) that are connected to a particular namespace.
To retrieve the socket id's of the default namespace (/):
let clientIds = Object.keys( io.of('/').connected );
(where io is the server instance)
As of today, socket.io implemented a function called fetchSockets() on server side to retrieve all sockets that are currently connected on the server-side. (Source : https://socket.io/docs/v4/server-instance/#fetchSockets)
You can then use it like this :
const io = require("socket.io")
async function retrieveSockets() {
const connectedSockets = await io.fetchSockets()
}
As far as i tested, you can even execute action on sockets thanks to that, like emitting events, joinings rooms...etc
const count = io.engine.clientsCount;
This seems like a more inclusive approach and may be the same count of Socket instances in the main namespace as below. But depending on namespaces and usage they could be different.
const count2 = io.of("/").sockets.size;
https://socket.io/docs/v4/server-api/#engineclientscount
I believe it is Object.keys(io.sockets.connected).length. Check server api http://socket.io/docs/server-api/

Socket IO - Socket.emit is sent to all clients

I am creating a game using socket io. A player connects like this:
var playerName = document.getElementById("name").value;
socket.emit('setup player', {
name : playerName
});
Then on the server, the player is setup and his information is sent back to the client:
function onSetupPlayer(data) {
...
var newPlayer = new Player(x, y, color, data.name,
this.id, scale);
socket.emit('setup game', {
localPlayer : newPlayer
});
...
sockets[this.id] = socket;
}
The following call:
socket.emit('setup game', {
localPlayer : newPlayer
});
Should send the setup data only back to the client that requested the setup to be done originally. However the setup call gets send to everyone in the lobby.
Could this have anything to do with the fact that I am using localhost to test it? I am also testing it on the same machine by using different tabs. If this is what is causing the issue, is there a way to resolve it? Since this is pretty annoying when testing my game.
EDIT:
Initialization:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var socket = require('socket.io')(http);
var path = require('path');
var io = require('socket.io')(80);
...
var setEventHandlers = function() {
socket.sockets.on("connection", onSocketConnection);
};
Listening for connection:
function onSocketConnection(client) {
...
client.on("setup player", onSetupPlayer);
...
};
And on the client side I have this:
var setEventHandlers = function() {
socket.on("setup game", onSetupGame);
...
}
socket.emit send event to everyone excepts this. To send data back to this user try
io.to(socket).emit()

node.js eventListener not listen

i'm a noob of node.js and i'm following the examples on "Node.js in action".
I've a question about one example :
The following code implements a simple chat server via telnet. When i write a message, the script should send message to all connected client.
var events = require('events');
var net = require('net');
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id,client){
this.clients[id] = client;
this.subscriptions[id] = function(senderId,message){
if(id != senderId){
this.clients[id].write(message);
}
};
this.on('broadcast',this.subscriptions);
});
var server = net.createServer(function(client){
var id = client.remoteAddress+':'+client.remotePort;
client.on('connect',function(){
channel.emit('join',id,client);
});
client.on('data',function(data){
data = data.toString();
channel.emit('broadcast',id,data);
});
});
server.listen(8888);
But when i try to connect via telnet and send a message it doesn't work.
Thanks
A couple issues I noticed. See the comments in the code.
var events = require('events');
var net = require('net');
var channel = new events.EventEmitter();
channel.clients = {};
channel.subscriptions = {};
channel.on('join',function(id, client) {
this.clients[id] = client;
this.subscriptions[id] = function(senderId,message) {
if(id != senderId)
this.clients[id].write(message);
};
//added [id] to "this.subscriptions"
//Before you were passing in the object this.subscriptions
//which is not a function. So that would have actually thrown an exception.
this.on('broadcast',this.subscriptions[id]);
});
var server = net.createServer(function(client) {
//This function is called whenever a client connects.
//So there is no "connect" event on the client object.
var id = client.remoteAddress+':'+client.remotePort;
channel.emit('join', id, client);
client.on('data',function(data) {
data = data.toString();
channel.emit('broadcast',id,data);
});
});
server.listen(8888);
Also note: If a client disconnects and another client sends a message then this.clients[id].write(message); will throw an exception. This is because, as of now, you're not listening for the disconnect event and removing clients which are no longer connected. So you'll attempt to write to a client which is no longer connected which will throw an exception. I assume you just haven't gotten there yet, but I wanted to mention it.

JavaScript - objects liefetime

I'm trying to create a node.js server using socket.io. At the moment is just proof on concept.
I created 2 files, first for server and anther for server side user.
server-core.js
'use strict';
var io = require('socket.io').listen(4567);
var user = require('./server-user');
var users = [];
io.sockets.on('connection', function(socket){
var su = new user.ServerUser(socket);
users[socket.id] = su;
socket.on('auth', su.auth);
socket.on('disconnect', su.disconnect);
});
io.sockets.on('disconnect', function(socket){
console.log('disconnect');
users[socket.id].disconnect();
});
console.log('Server started');
server-user.js
var ServerUser = (function(){
function ServerUser(socket){
this.socket = socket;
console.log('serverUser-ctor ' + this.socket)
}
ServerUser.prototype.auth = function(data){
console.log('auth received\r\n' + data);
this.socket.emit('auth', {
Id: data.Id,
Timestamp: data.Timestamp,
StringField: data.StringField
});
}
ServerUser.prototype.disconnect = function(){
console.log('Client disconnected');
}
return ServerUser;
})();
module.exports = {
ServerUser: ServerUser
};
my C# client connects fine to server, but when user-server tries to send the answer back the this.socket is undefined in ServerUser.prototype.auth method. This tell me that the instance of the ServerUser that I create in server-core is not being hold and when 'auth' method is called a new instance of object is actually being created.
To proof this I replaced this line
socket.on('auth', su.auth);
with such one
socket.on('auth', function(data){su.auth(data);});
After this it worked as needed.
Is this the correct way to write JS code?
Is there a better way to separate logic under separate files and classes when writing large node.js applications?
Thx for any opinions.
The problem is the invocation context. When you pass su.auth to socket.on(), this no longer refers to su inside of auth. So, there are a couple of ways to fix that. Using an anonymous function, as you found, is one. Function.bind is another:
socket.on('auth', su.auth.bind(su));

Categories