nothing happens when i emit some value to socket server - node.js

I have an expressjs server code which listen to a socket port like what you see below.
websocket.on('connection', (socket) => {
console.log('A client just joined on', socket.id);
websocket.on('messageIM', (message) => {
console.log('msg:'+message)
});
});
my client side application is a react-native mobile project which contains a code like this:
constructor(props) {
super(props);
this.socket = SocketIOClient('http://192.168.140.51:3000/');
}
and i get client connect 'A client just joined on ***' log on server console, means the connection to the server is successfully . but when i emit some variable .... nothing will happens in server side!...
call()=>{
this.socket.emit('messageIM','Hi server')
}
means when i call above call() function nothing happens in server.
this are the codes i'v written in both client and server side please give some help if you have some experience with that .

Looks like you used the wrong variable to listen on. The connection event returns the socket which is what you want to use. Rename websocket.on('messageIM' to socket.on('messageIM'
websocket.on('connection', socket => {
console.log('A client just joined on', socket.id);
socket.on('messageIM', message => {
console.log(`msg: ${message}`)
});
});

Related

How to ensure a single, private ssh connection using ssh2 with socket.io in Meteor

I am using ssh2 and socket.io to enable a real-time ssh connection to a remote server for users of my Meteor 1.8.1 app. The app runs on Ubuntu under Nginx and Phusion Passenger. Here is what the app needs to do:
Each authorised user already has an account on the remote server.
A user will start a session by entering their credentials and clicking a "connect" button in the app.
The user can browse directory listings within their home directory on the remote server.
No user should have access to another user's ssh session.
Their ssh session should be removed from the server when the user clicks a "disconnect" button.
I have the ssh connection working but I can't figure out how to destroy the ssh connection at the end of the user's session. Each time they press disconnect" then "connect", another ssh session is started and the old ssh session is still operational, so each ssh command that is sent is executed multiple times and multiple responses are sent to the browser.
I'm also concerned that the connection isn't secure; in development I'm creating the server with require('http').createServer();. In production, on my Ubuntu server with SSL configured, is it enough to use require('https').createServer(); or is there other configuration required, e.g. of Nginx? Socket.io falls back to older technologies when websocket isn't available; how is that secured?
Main question: why am I seeing duplicate SSH sessions every time the user disconnects and then connects?
Secondary question: where can I find up to date instructions on how to secure socket.io? Or should I give up on socket.io and use WebSocket?
I have read a lot of articles and stack overflow posts, but I'm finding this very confusing and most of the material is out of date. For example socketio-auth is not maintained. I can find almost nothing in the Socket.io documentation on authentication or authorization - there is a handshake entry but it's not clear to me from this whether it's the function I need or how to use it.
Here's my code.
Server
io.on('connection', (socket) => {
console.log('socket id', socket.id); // this shows a new id after disconnect / reconnect
const conn = new SSHClient();
socket.on('disconnect', () => {
console.log('disconnect on server');
conn.end();
});
conn.on('ready', () => {
socket.emit('message', '*** SSH CONNECTION ESTABLISHED ***');
socket.emit('ready', 'ready');
conn.shell((err, stream) => {
stream.write('stty -echo \n'); // don't echo our own command back, or the user's password...
if (err) {
return socket.emit('message', `*** SSH SHELL ERROR: ' ${err.message} ***`);
}
socket.on('path', (path) => {
// path is a request for a directory listing
if (typeof path === 'string') {
const bashCommand = `ls -l ${path} --time-style=full-iso`;
console.log('*** WRITE'); // if you disconnect and reconnect this runs twice. Disconnect and reconnect again, it runs 3 times.
console.log('socket id again', socket.id); // this shows the same new socket id each time
stream.write(`${bashCommand} \n`);
}
});
stream.on('data', (d) => {
socket.emit('data', response); // tell the browser!
}).on('close', () => {
conn.end();
});
});
}).on('close', () => {
socket.emit('message', '*** SSH CONNECTION CLOSED ***');
}).on('error', (err) => {
socket.emit('message', `*** SSH CONNECTION ERROR: ${err.message} ***`);
}).connect({
'host': hosturl,
'username': ausername,
'agent': anagent, // just for dev I'm using public / private key from my local machine but this will be replaced with the user's entered credentials
});
}).on('disconnect', () => {
console.log('user disconnected');
});
server.listen(8080);
Client:
const io = require('socket.io-client');
const EventEmitter = require('events');
class MyEmitter extends EventEmitter {};
const myEmitter = new MyEmitter();
const PORT = 8080;
let socket;
myEmitter.on('connectClicked', () => {
if (socket) {
this.connected.set(socket.connected);
}
if (this.connected.get() === false) {
socket = io(`http://localhost:${PORT}`);
socket.on('connect', () => {
this.connected.set(true);
socket.on('ready', () => {
console.log('ready');
});
// Backend -> Browser
socket.on('message', (data) => {
console.log('socket on message', data);
});
// Backend -> Browser
socket.on('data', (data) => {
console.log('got data', data);
this.parseResponse(data); // client function to handle data, not shown here
});
// Browser -> Backend
myEmitter.on('selectDirectory', () => {
console.log('*** SELECT DIRECTORY');
socket.emit('path', pathArray.join('/')); // path array is set in client code, it is a simple array of directory names
});
socket.on('disconnect', () => {
console.log('\r\n*** Disconnected from backend***\r\n');
this.connected.set(false);
});
});
}
myEmitter.on('disconnectClicked', () => {
socket.disconnect();
});
});
The answer to keeping the ssh connections separate is to maintain a list of current ssh connections and rework the code so that received ssh data is sent only to the browser that corresponds to the incoming message.
I've also given up on socket.io because I can't be confident about security. I'm now using Meteor's inbuilt DDP messaging system via the Meteor Direct Stream Access package. I think this avoids opening up any new points of access to my web server.

Nodejs/express server uses one socket.id for 2 RN clients in message saving

The nodejs (10.16) and express (4.16) backend server (server) runs with socket.io 2.2.0 for a chat app. The message received on the server will be broadcast to the clients connecting to the same room (channel). The socket.io instance is created in index.js:
const io = require('socket.io')(server);
io.on('connection', async (socket) => {
socket.my_id = "";
console.log("socket.id : ", socket.id);
app.set("socket", socket);
console.log("Socketio server is initialized");
//disconnect
socket.on('disconnect', async function() {
//if (socket.my_id) helper.RemoveSocketUser(user.fort_token, socket.my_id);
console.log('disconnected event');
});
});
server.listen(port, () => {};
Then after a message is saved on the server, the socket is used to broadcast to the clients in the same room.
try {
await msg.save();
msg.user_name = req.user.name;
msg.user_avatar = req.user.user_data.avatar;
const io = req.app.get("io");
const socket = req.app.get('socket');
const room = msg.event_id.toString();
socket.my_id = req.user.id;
socket.join(room);
console.log("socket in new message : ", socket.id);
console.log("msg before broadcast : ", msg.data.msg_body);
io.to(room).emit("event message", msg);
return res.status(200).send(req.body.data.msg_body);
} catch (err) {
console.log("Error in saving/braodcasting a new message", err);
return res.status(400).send(err.message);
};
From the console output, the socket.id is the same for 2 clients connecting to the same room and chatting. Here is a output for Android emulator running on port 8081:
socket in new message : b0po9l6hGZUi9xVDAAAE
msg before broadcast : 8081
Here is another android emulator running on port 9090:
socket in new message : b0po9l6hGZUi9xVDAAAE
msg before broadcast : 9090
However the socket.id on clients side is not the same. What causes the server using the same socket.id for 2 clients?
What you are trying to do is accessing socket object stored in express,
which will update socket object every time new socket get connected that's why you are getting same socket id [ last connected ].
to access specific socket from outside the io connection scope, you have to get the socket instance from io object.
you need to store socket id somewhere in database or memory like redis.
const socketid = `get user's latest connected socket id.`
cont socket = io.sockets.sockets[socketid];
socket.emit('req', { data: "something"})

Socket.io keeps multiple connected sockets alive for 1 client

I am using Socket.io to connect a React client to a Node.js server and the query option in socket.io to identify uniquely every new client. However, the server creates multiple sockets for every client and, when I need to send something from the server, I don't know which socket use, because I have more than one, and all of them are connected.
The client code:
import io from "socket.io-client";
...
const socket = io(process.env.REACT_APP_API_URL + '?userID=' + userID, { forceNew: true });
socket.on('connect', () => {
socket.on('new-order', data => {
const { add_notification } = this.props;
add_notification(data);
});
The server code:
....
server = http
.createServer(app)
.listen(8080, () => console.log(env + ' Server listening on port 8080'));
io = socketIo(server);
io.on('connection', socket => {
const userID = socket.handshake.query.userID;
socket.on('disconnect', () => {
socket.removeAllListeners();
});
});
And here the server-side that emits events to the client:
for (const socketID in io.sockets.connected) {
const socket = io.sockets.connected[socketID];
if (socket.handshake.query.userID === userID) {
// Here, I find more than one socket for the same condition, always connected.
socket.emit(event, data)
}
}
Here, it is possible to see all these socket for the same client:
I tried to send events for all socket from a given userID, however, multiple events are triggered to the client, showing duplicated data to the user. I also tried to send events to the last socket, but, sometimes it works, sometimes doesn't.
Someone have a clue how to uniquely identify a socket when there are several clients?

nodejs socket.io - connected to server but emit doesn't do anything

I'm starting to work with Socket.io and my nodeJS API
I succeeded to get my user connected, and showed a message on my server.
But now, I'm trying to send data to my client -> then server -> then client again etc.
But when I use emit nothing appends... So this i my code :
SERVER SIDE
io.on('connection', function(socket){
console.log("user connected") // I see that
socket.emit('text', 'it works!'); //
socket.on('test1', function (data) {
console.log('received 1 : '); // Never showed
console.log(data); // Never showed
});
}
CLIENT SIDE
var socket = io.connect(myUrl); // good connection
socket.emit ('test1', {map: 4, coords: '0.0'}); // never showed on the server side
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
Any ideas?
thanks !
Your Starter Code seems to be valid, you need to check two things :
if you successfully included the socket.min.js in the client side
if you re having any error printed in the console
On the client side, you have to wait until the connection succeeds before it is safe to send data to the server. Connecting to the server is not synchronous or instantaneous (thus it is not ready immediately). You are trying to send data before the connection is ready.
Put your first send of data inside a socket.on('connect', ...) handler.
var socket = io.connect(myUrl); // good connection
// send some data as soon as we are connected
socket.on('connect', function() {
socket.emit ('test1', {map: 4, coords: '0.0'});
});
socket.on('text', function(text) {
alert(text); // never showed
socket.emit('test', { "test": "test2" });
});
this worked for me
CLIENT SIDE
//sending custom data to server after successful connection
socket.on('connect', function(){
this.socket.emit('client-to-server', {map: 4, coords: '0.0'});
});
//listening the event fired by the socket server
socket.on('server-to-client', function(dataSendbyTheServer){
// do whatever you want
console.log(dataSendbyTheServer);
});
SERVER SIDE
io.on('connection', function(socket) {
// listening the event fired by the client
socket.on('client-to-server', function (data) {
console.log('received 1 : ');
// sending back to client
io.emit('server-to-client', data)
});
});

How to cleanly disconnect from a namespace in socket.io?

I have been trying to disconnect from a namespace or even from the main socket connection itself but have been failing. Below is my code
Server Side:
socket.on('userDisconnect', function () {
socket.disconnect();
console.log("User Disconnected");
});
Client Side:
// already connected to /world namespace
socket.emit('userDisconnect');
socket.disconnect();
socket = io.connect('http://something/india' );
I tried disconnecting from both client and serve side but it doesnt work. Can anyone point out the mistake.
This is what is been written to console by socket.io
info - booting client
debug - websocket writing 0::/world
User Disconnected
debug - client authorized for /india
debug - websocket writing 1::/india
/world is the namespace its trying to disconnect from and then its trying to connect to /india namespace.
This worked for me
broadcastSocket.packet({ type: 'disconnect' });
broadcastSocket.$emit('disconnect');
disconnectNamespace(broadcastSocket.name, broadcastSocket.socket);
function disconnectNamespace (name,socket) {
if (socket.namespaces[name]) {
var nsp = socket.of(name);
nsp.packet({ type: 'disconnect' });
nsp.$emit('disconnect');
delete socket.namespaces[name];
if (Object.keys(socket.namespaces).length === 0) {
socket.disconnect();
}
}
};
For socket.io v.1.3.2
Create with:
sio = io('ws://localhost:13000/device');
Delete with:
sio.disconnect();
delete sio.io.nsps[sio.nsp]; // sio.nsp = '/device'
delete sio;
This worked for me.
On the server
nsp.on('connection', (socket) => {
setTimeout(() => {
socket.disconnect(false)
}, 5000);
});
Disconnects this client. If the value of close is true, closes the underlying connection. Otherwise, it just disconnects the namespace. It's in the documentation https://socket.io/docs/server-api/
It doesn't look like you told the client to wait for disconnect before reconnecting.
// already connected to /world namespace
socket.emit('userDisconnect');
socket.on('disconnect', function () {
socket = io.connect('http://something/india');
// stuff with india socket
});
Use disconnect() method on the server or on the client (or both like your did in your example). When you first connect to the server, add 'forceNew':false to the client connect method, something like this:
var socket = io('http://localhost:3001', {'forceNew':false});

Resources