How to kick somebody out on socket - node.js

I am on a websocket (socket.io) and I want to be able to force disconnect on a given user. I use this on my server file:
// kickout
socket.on('kickout', (sckid) => { //sckid is the socket.id of the kicked-out user
io.to(sckid).emit('kicked');
});
});
// kicked out
socket.on('kicked', () => {
socket.disconnect();
});
Then I do socket.emit('kickout', 'someusersocketid'); on my frontend but it won't work for some reasons. Seems like the server listens to "kickout" alright but so to "kicked". Why is that?

Try this one:
var clients = {}
sockets.on('connection', function(socket) {
clients[socket.id] = socket;
socket.on('disconnect', function() {
delete clients[socket.id];
});
});

Related

Socket.io, Node, Corodva, I don't recive message in client receptor

I have a problem when I try send message from a client emisor with "emit" and I try catch the message with "on" in a client receptor.
I don't know what is the problem, my code is this:
Emisor Client:
socket.emit("callDriver", data);
Receptor Client:
socket.on("sendToDriver", function(data){
console.log(data);
})
Server:
var io = require('socket.io')(server);
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
Thanks community
Guys I resolved the problem, it's strange in the official documentation of Socket.io they say that when you send data in a .emit you should send this with "socket.emit()" (server side) but I try change socket for io and with this mode work it.
In conclusion:
// I changed this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
socket.emit('sendToDriver', data);
})
})
// for this:
io.on('connection', function(socket){
socket.on('callDriver', function(data){
console.log(data);
io.emit('sendToDriver', data);
})
})
Thanks guys!
Here is a simple rooms solution for you. The init() part is very low-tech/simple but you did not say how you intend to populate the socket server with the client userId/session-data when you connect to the server for the first time.
//Client
socket.on('connect',()=>{
socket.on('init',()=>{
socket.emit('init', 'userid')
})
})
socket.on("sendToDriver", function(message){
console.log(message);
})
sendMessage(message){
let data = {userId: "userId", message: message}
socket.emit("callDriver", data);
}
//Server
var io = require('socket.io')(server);
//Triggered by each client separately.
io.on('connection', function(socket){
socket.on('init', (driverId)=>{
//When your web socket starts for the first time, each user creates their own room with their main userId that is used in your mobile app.
//Your setup is so basic, that the server('connection') -> server.emit('init') -> client.on('init') -> client.emit('init') flow is the most sane example for now.
//However this init() setup is primitive -- you need an authentication flow and to pass up the userId/session data with a socket.io 'middleware' function or the 'socket.io-auth' library (recommended)
socket.join(driverId)
})
socket.emit('init')
//Data sent to callDriver will contain the userId of the desired receipient. Since this user is already waiting in that room for us, we join it,
//send the message, and then leave immediately.
socket.on('callDriver', function(data){
socket.join(data.driverIdToCall)
socket.to(data.driverIdToCall).emit('sendToDriver', data.message);
socket.leave(data.driverIdToCall)
})
})

Socket IO not properly closing connection

I'm tailing a log file and stream the new lines to a websocket.
Since I have multiple logs, I let the user choose the log file and then get the details of that log.
The problem is that when I close a connection in order to see a different log, the connection does something weird, that when I start it again, it streams the data twice. If I close the connection and re-open it again, it streams 3 times the data, so on and so forth.
My package.json:
{
"socket.io": "^2.0.3",
"socket.io-client": "^2.0.3"
}
Client side
$("#detailsBtn").click(function (e) {
e.preventDefault();
$.get('/get/details', {
// some-data
}, () => {
if (socket) socket.close();
socket = io('http://localhost:4000', {forceNew: true});
socket.on('connect', () => {
console.log('connected');
});
socket.on('newLine', function (msg) {
// do-stuff
});
});
});
$('#closeBtn').click(function () {
socket.disconnect();
socket.close();
});
Server side
app.get('/details', (req, res) => {
const tail = spawn('ssh', ['root#' + req.query.srv, req.query.script]);
io.on('connection', function (socket) {
console.log(`connect ${socket.id}`);
socket.on('disconnect', () => {
console.log(`DISconnected ${socket.id}`);
});
tail.stdout.on('data', function (data) {
socket.emit('newLine', {message: data});
});
});
return res.sendStatus(200);
});
Now when simulating the button click, I expect the socket and connection to be closed, in order to make a new one.
Server console log (each time I click the button only once)
Server listening on localhost:4000
**click on detailsBtn**
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 16.003 ms - -
connect YyYHFI9CARpBHaxoAAAB
**click on closeBtn**
DISconnected YyYHFI9CARpBHaxoAAAB
**click on detailsBtn**
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 6.308 ms - -
connect vzfBnUPHUqYXd5qaAAAC
connect vzfBnUPHUqYXd5qaAAAC
**click on closeBtn**
DISconnected vzfBnUPHUqYXd5qaAAAC
DISconnected vzfBnUPHUqYXd5qaAAAC
**click on detailsBtn**
GET /get/details?srv=myserver.google.com&script=%2Fusr%2Fbin%2Ftail 304 4.677 ms - -
connect 3quEe5G1gFDJ2BvrAAAD
connect 3quEe5G1gFDJ2BvrAAAD
connect 3quEe5G1gFDJ2BvrAAAD
**click on closeBtn**
DISconnected 3quEe5G1gFDJ2BvrAAAD
DISconnected 3quEe5G1gFDJ2BvrAAAD
DISconnected 3quEe5G1gFDJ2BvrAAAD
What am I doing wrong?
As you see in the console logs, the connect and disconnect shows the same socketID. This indicates that the event handler is triggered many times.
From your code you define a new event handler for 'connection' every time the '/details' route is getting a request.
So a better aproach would be...
io.on('connection', function (socket) {
console.log(`connect ${socket.id}`);
socket.on('disconnect', () => {
console.log(`DISconnected ${socket.id}`);
});
tail.stdout.on('data', function (data) {
socket.emit('newLine', {message: data});
});
});
app.get('/details', (req, res) => {
const tail = spawn('ssh', ['root#' + req.query.srv, req.query.script]);
return res.sendStatus(200);
});
So the comments here directed me to the solution.
I had duplicate event handlers for both the socket and the tail.
I called the initiation of the connection each time a user clicked the button, and I spawned a tail child process each time the URL was accessed
Here is how I fixed it:
Socket
1.Moved the io.on('connection'...) outside of the app.get handler as suggested by #alex-rokabilis
2.Created an event emmiter of my own:
const events = require('events');
const eventEmitter = new events.EventEmitter();
3.Inside io.on('connection'...), instead of listening to tail.stdout event, I listened to my eventEmitter event in order to be able to use the tail outside of the app.get handler
io.on('connection', function (socket) {
eventEmitter.on('newLine', (data) => {
socket.emit('newLine', {line: data});
});
});
4.In the app.get handler, I listen to tail.stdout.on('data'... and send an eventEmitter event that would be handled inside the io object:
app.get('/details', (req, res) => {
let tail = spawn('ssh', ['root#' + req.query.srv, req.query.script]);
tail.stdout.on('data', (data) => {
eventEmitter.emit('newLine', data.toString().replace(/\n/g, '<br />'));
});
});
5.On client, I moved the io initialization outside of the ajax call, defined socket in a way I could use further in the script.
let socket = io('http://localhost:4000', {forceNew: true});
socket.on('connect', () => {
console.log('connected');
});
socket.on('newLine', function (msg) {
// do-stuff
});
$("#detailsBtn").click(function (e) {
e.preventDefault();
$.get('/get/details', {
// some-data
});
});
Tail
This was a bit hard to find, I always thought the problem is with the socket-io rather than the tail.
Inside io.on('connection'..., I added a socket listener for an event named closeConnection that emits closeConnection to my eventEmitter, that in turn kills the tail child process:
io.on('connection', function (socket) {
eventEmitter.on('newLine', (data) => {
socket.emit('newLine', {line: data});
});
socket.on('closeConnection', () =>{
console.log('got connection close from client');
eventEmitter.emit('closeConnection');
});
});
And inside the app.get controller:
app.get('/details', (req, res) => {
let tail = spawn('ssh', ['root#' + req.query.srv, req.query.script]);
tail.stdout.on('data', (data) => {
eventEmitter.emit('newLine', data.toString().replace(/\n/g, '<br />'));
});
eventEmitter.on('closeConnection', () => {
tail.stdin.pause();
tail.kill();
});
});
And in the client, each time I want to close the connection, I just:
socket.emit('closeConnection');
That was tough.

Socket.io communicating from server to client not happening

i am trying to do a very simple real time notification with socket.io. for some reason i can't receive data or fire the event from server to client but from client to server yes. let me show my code:
Client Side
ngOnInit() {
this.socket.on('connect', function (res: any) {
console.log('Socket.io is connected on client side!'); // it shows on client console
});
this.socket.on('alarmsreceived', function (res: any) {
console.log(res + ' i am here now'); // is not firing
});
}
// this method fires from a click button
objectStatus = () => {
this.socket.emit('alarmsystem', 'i am client going to server');
}
Server
var io = require('socket.io').listen(server);
var connections = [];
io.of('/api/v1/monitoring').on('connect', function(socket){
connections.push(socket);
console.log('Connected %s sockets', connections.length); // i see connection on cmd
socket.on('disconnect', function() {
connections.splice(connections.indexOf(socket), 1);
console.log('Connected %s sockets', connections.length);
});
socket.on('alarmsystem', function(res) {
console.log(res); // this shows me the message from client
io.sockets.emit('alarmsreceived', 'I am server heading to client');
});
})
it seems pretty straight forward, but not firing the client event. Can someone help me what i am doing wrong here? Thanks in advance

Expose socket.io listeners after client action

Is there a way to set up socket.io listeners for certain clients after they execute a command? For example:
socket.on('setupServer', function (data) {
console.log("setupServer called");
// Now set up listeners
socket.on('serverAction', function (data) {
console.log('Listener for clients calling setupServer');
});
});
In the above, a client has connected and has issued a 'setupServer' command to the node.js server. The server now listens for 'serverAction' from the specific client. Other clients won't be able to use 'serverAction' without calling 'setupServer' first.
You could create a room and validate some data from user and then join those users to that room, after that emit some events to that users in that room.
Something like this.
server.js
var io = require('socket.io')(server);
io.on('connection',function(socket){
socket.emit('auth_user')
socket.on('response_from_user',function(data){
if(data.name === "Blashadow"){
//join that user to the room
socket.join('/room',function(){
//emit some custom event to users in that room
io.in('/room').emit('custom_event_room', { info: 'new used connected from room' });
});
}
});
});
client.html
var socket = io('localhost');
socket.on('auth_user', function (data) {
socket.emit('response_from_user', { name : "Blashadow" });
});
socket.on('custom_event_room',function(data){
console.log(data);
});

socket.io force disconnect client

I may be doing something wrong here but I can't get my head around this.
The following does not work:
client
$("#disconnectButton").click(function() {
socket.emit("disconnect");
});
server
socket.on("disconnect", function() {
console.log("this never gets called");
});
Can't I manually call the disconnect event from the client side? Because the following works:
client
$("#disconnectButton").click(function() {
socket.emit("whatever");
});
server
socket.on("whatever", function() {
socket.disconnect();
console.log("this gets called and disconnects the client");
});
'disconnect' event is Socket.io event,if you use emit to call the 'disconnect',may be cause other problom
so:
$("#disconnectButton").click(function() {
socket.emit("disconnect");
});
replace:
$("#disconnectButton").click(function() {
socket.disconnect();
});
For now, socket.emit('disconnect') or socket.disconnect() doesn't work.
The correct syntax to disconnect to the socket server is
socket.close()

Resources