Hi I am trying to make a tracker app and I'm using socket.io for both server and client. On my client app, I want to disregard message event whenever my browser is not on focus. my code is like this for the client app :
const socket = io('http://localhost:4000');
const [browserState, setBrowserState] = useState('');
useEffect(() => {
socket.on('connect', () => {
console.log('connected');
socket.on("message", payload => {
//payload need to be passed to Map component
console.log(payload);
});
});
},[]);
useEffect(() => {
document.onvisibilitychange = function(){
setBrowserState(document.visibilityState)
}
if(browserState === 'hidden') socket.volatile.emit("message", payload => payload)
},[browserState]);
and on my server is just simply:
io.on('connection', socket => {
socket.on('message', (payload)=>{
console.log(payload)
io.emit('message', payload)
});
The problem is on the client-side for the code socket.volatile.emit("message", payload => payload). if I use socket.volatile.on it's working. but I still receive message event on the client. if I use socket.volatile.emit the server is crashing.
Additional Question: is it okay if my client side io.protocol = 5 and my server is io.protocol = 4?
I'm really new to this. Please advise. :) Thanks!
It can be discarded easily by not replying to incoming sockets
io.on('connection', socket => {
socket.on('message', (payload)=>{
console.log(payload)
// removed this line io.emit('message', payload)
});
Related
I have 3 components device, server and frontend (admin).
Server
Starts socket.io server with 2 namespaces /admin and /client.
If socket from /admin namespace sends data, server passes it along to /client namespace. If socket from /client namespace sends data, server passes it along to /admin namespace.
const io = require('socket.io');
const device = io.of('/device');
const admin = io.of('/admin');
device.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [DEVICE] TO [ADMIN]")
admin.emit('data', data);
})
});
admin.on('connection', (socket) => {
socket.on('data', (data) => {
console.log("PASSING DATA FROM [ADMIN] TO [DEVICE]")
device.emit('data', data);
});
});
io.listen(80);
Device
Uses socket.io-client to connect to socket.io server.
Starts interactive shell session using node-pty.
const io = require('socket.io-client');
const socket = io('http://localhost:80/client');
const os = require('os');
const pty = require('node-pty');
const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
const ptyProcess = pty.spawn(shell, [], {
name: 'xterm-color',
cols: 80,
rows: 30
});
socket.on('connect', () => {
});
// INPUT DATA
socket.on('data', (data) => {
ptyProcess.write(data);
});
// OUTPUTING DATA
ptyProcess.onData = (data) => {
socket.emit('data', data)
}
Frontend
Finally I have the frontend which uses xterm.js to create a terminal inside the browser. I am using vue. The browser client as well connects to socket.io server on the /admin namespace. Basically I have this :
<template>
<div id="app">
<div id="terminal" ref="terminal"></div>
</div>
</template>
<script>
import { Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
import { io } from 'socket.io-client';
export default {
mounted() {
const term = new Terminal({ cursorBlink : true });
term.open(this.$refs.terminal);
const socket = io('http://localhost:80/admin');
socket.on('connect', () => {
term.write('\r\n*** Connected to backend***\r\n');
term.onData((data) => {
socket.emit('data', data);
})
socket.on('data', (data) => {
term.write(data);
});
socket.on('disconnect', () => {
term.write('\r\n*** Disconnected from backend***\r\n');
});
});
}
}
</script>
Problem
❌ Starting the pty session seems to work, at least there are now errors reported. However it seems the onData listener callback is never fired, even when I ptyProcess.write() something.
❌ Getting input from xterm all the way to the device ptyProcess.write does not seem to work. I can see the data passed along through the socket.io sockets all the way to the device. But from there nothing happens. What do I miss ? Also I don't see my input in the xterm window as well.
After switching from child_process to using node-pty to create an interactive shell session I almost had it right. Following the node-pty documentation it marked the on('data') eventhandler as deprecated. Instead I should use .onData property of the process to register a callback. Like this:
ptyProcess.onData = function(data) {
socket.emit('data', data);
};
But that didn't do anything. So I switched back to the depracated way of adding an event listener:
ptyProcess.on('data', function(data) {
socket.emit('data', data);
});
Now I have a working interactive shell session forwarded from a remote device through websocket inside my browser ✅.
UPDATE
Did more digging for onData property. Realized it's not a property but a method so I used it wrong. This would be the prefered way :
ptyProcess.onData(function(data) {
socket.emit('data', data);
});
Which also works as expected 👍
I'm trying to create a user to user chat application - no group chat or anything.
I'm using NodeJS and Socket.io on the backend and React Native on the frontend.
I ended up having a Map that stores a user id and it's corresponding socket id, my problem is that only when a user connects to the server, he will get a socket id.
But what if User A is connect and is trying to send a message to User B, and User B is not connected, so it does not have a socket id, I don't really know what to do then.
This is what I got so far:
io.on("connection", (socket: Socket) => {
//Whenever a user will connect, the user will emit 'initiate' to register itself and it's socket id to the server.
//We will be using this userSocketMap to send messages between users.
socket.on(SocketEvents.INITIATE, (data) => {
const uid = data.uid;
const socketID = socket.id;
userSocketMap.set(uid, socketID);
});
//This function will get called when a user is sending message to another user.
socket.on(SocketEvents.SEND, (data) => {
const to = data.to;
const from = data.from;
const content = data.content;
const payload: MessagePayload = {
to: to,
from: from,
content: content,
};
const dstUser = userSocketMap.get(to); // getting the socket id of the receiver.
// '/#' is the prefix for the socketID, if the socketID already has this prefix, this should be deleted - need to check this.
//MessageEvent.RECEIVE is used to signal the dstUser to receive a message.
io.to("/#" + dstUser).emit(SocketEvents.RECEIVE, { payload: payload });
});
socket.on(SocketEvents.DISCONNECT, (socket: Socket) => {
const userID = getByValue(socket.id);
if (!userID) return;
userSocketMap.delete(userID);
});
});
You should do two things when working with react-native and socket.io in case user lost internet connection. Use socket.io heartbeat mechanism inorder to get the users that lost connection and are not responding and user NetInfo package to inform the mobile user that he has lost internet connection.
Socket.io
var server = app.listen(80);
var io = socketio(server,{'pingInterval': 2000});
io.on("connection", (socket: Socket) => {
socket.on(SocketEvents.INITIATE, (data) => {
const uid = data.uid;
const socketID = socket.id;
userSocketMap.set(uid, socketID);
})
socket.on('heartbeat', (socket: Socket) => {
const userID = getByValue(socket.id)
userSocketMap.MARK_USER_AS_INACTIVE(userID)
})
});
React-Native - use NetInfo - it used to be part of the core but got separated to a community module
import NetInfo from "#react-native-community/netinfo";
NetInfo.fetch().then(state => {
console.log("Connection type", state.type);
console.log("Is connected?", state.isConnected);
});
const unsubscribe = NetInfo.addEventListener(state => {
console.log("Connection type", state.type);
console.log("Is connected?", state.isConnected);
});
// Unsubscribe
unsubscribe();
I am using mqttjs and socketio on my nodejs backend.
I am using angular as my frontend framework.
On my frontend there are 3 routes.
All requires socket connection for real time data.
So on ngOnInit i run client side socket io connection code and on ngOnDestroy I will run socket disconnect as well.
And in my server side code (index.js) there are mainly 3 actions that is happening.
const io = require('socket.io')(server)
mqtt.createConnection();
mqtt.mqttSubscriptions(io);
mqtt.mqttMessages(io);
These are the mqtt methods:
const createConnection = () => {
let options = {
protocol: 'mqtt',
clientId: process.env.MQTT_CLIENT_ID,
username: process.env.MQTT_USERNAME,
password: process.env.MQTT_PASSWORD,
};
client = mqtt.connect(process.env.MQTT_HOST, options);
client.on('connect', function() {
winston.info('MQTT connected');
});
client.on('error', function(err) {
winston.error(err);
});
};
const mqttSubscriptions = io => {
winston.info(`Socket connected.`);
client.subscribe([TOPICS.DATA], function(error, granted) {
if (error) {
winston.error(error);
}
winston.info('Topics: ', granted);
});
};
const mqttMessages = io => {
io.sockets.on('connection', socket => {
winston.info(`Socket connected.`);
client.on('message', function(topic, message) {
let payload = JSON.parse(message.toString());
winston.info(topic);
winston.info(payload.id);
switch (topic) {
case TOPICS.DATA:
dataController.storeData(payload, io);
break;
default:
winston.error('Wrong topic');
break;
}
});
});
};
And on the datacontroller I am running
socket.emit()
My problem is everytime I navigate to a route and come back the dataController.storeData is called multiple times.
That is when I am at route A, and then navigate to route B and then back to A and then to C, the data is multiplied that many times of my route navigation. (In this case 4 times.)
I found that it is socket io and mqtt connection problem, but I don't know how to solve, since I am new to both of these.
Any help?
Scenario is i have a server where socket(1) runs i have one more server where socket(2) client connects to socket(1)
I have one browser socket which connects to socket(1)
Idea is to do request from browser and bring data from socket(2) server
Not sure how to difference between socket clients as all the sockets are similar to socket(1)
Ideally there will be multiple browser sockets and multiple socket(2) clients
Browser sockets can make request to any of the socket(2) clients
How to implement it using nodejs socket.io
Server
socket.on('action', (action) => {
if(action.type === 'server/hello'){
io.sockets.emit('broadcast',{ description: clients + ' clients connected!'});
console.log('Got hello data!', action.data);
}
});
Browser client
var socket = io.connect('localhost:3000', {reconnect: true});
socket.on('connect', function(data) {
socket.emit('joined', 'Hello World from client this is client plxx');
});
socket.on('response2', function(data) {
console.log("got it ", data);
$('#messages').append($('<li>').text(JSON.stringify(data)));
});
Server client
var io = require('socket.io-client');
var socket = io.connect('http://localhost:3000', {reconnect: true});
socket.on('broadcast', function (t) {
socket.emit("data", {data: 32})
console.log('broadcast! my host is est');
});
i should be able to communicate between socket clients
What I understood from your question is: you need to differentiate between sockets from different clients.
To solve that I would suggest simply emitting the socket source from the client on connect.
And on the server split the sockets into two lists.
Example:
Server
const BROWSER_CLIENTS = {};
const SERVER_CLIENTS = {};
io.on("connection", socket => {
socket.on("source", payload => {
if (payload == "browser")
BROWSER_CLIENTS[socket.id] = socket;
else if (payload == "server")
SERVER_CLIENTS[socket.id] = socket;
});
socket.on("disconnect", () => {
delete BROWSER_CLIENTS[socket.id];
delete SERVER_CLIENTS[socket.id];
});
});
Browser Client
socket.on("connect", () => {
socket.emit("source", "browser");
});
Server Client
socket.on("connect", () => {
socket.emit("source", "server");
});
Now when you receive an event you can detect from which source it originated. And if you need to send to all sockets of one type of clients you can simply do this:
Server
for (let i in BROWSER_CLIENTS)
BROWSER_CLIENTS[i].emit("Hello Browsers")
for (let i in SERVER_CLIENTS)
SERVER_CLIENTS[i].emit("Hello Servers")
EDIT: I found this link and thought you could make use of it. Socket.io Rooms
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