Socket IO flutter not connecting - node.js

I am facing an issue connecting my socket io flutter client to my nodejs socket io server.
I am aware of the compatibility issue between the node socket io package and the flutter socket io client package. Hence, I installed only compatible versions of dependencies on both ends.
i.e.,
for flutter
socket_io_client: ^1.0.2
and for server side.
{
"socket.io": "^2.4.1",
}
I have also tried the latest dependencies but I am getting the same timeout message in my logs,
Initially, I thought it was my server's issue, but I checked the connection using postman and it works.
Below I am adding my implementations for both server and client side,
const { socketGuard } = require('./middlewares/socketio.middleware');
let io;
module.exports = {
init: (server) => {
io = require("socket.io")(server, { cors: { origin: '*' } });
io.use(async (socket, next) => {
let result = await socketGuard(socket);
if (result.isValid) {
next();
}
else {
next(new Error("Not authorized"));
}
});
io.on("connection", (socket) => {
console.log(`${socket.id} : connected`);
});
return io;
},
get: () => {
if (!io) {
throw new Error("Socket io not initialized");
}
return io;
}
};
and for flutter, I have added the following lines in the init function,
io.Socket socket = io.io("http://192.168.1.14:5000");
socket.onConnect((data) {log("Hello world");});
socket.onConnectError((data) {log(data);});
socket.onError((data) {log(data);});
socket.on("message", (data) {log(data);});

As per the socket_io client readme
In Flutter env. not (Flutter Web env.) it only works with dart:io websocket, not with dart:html websocket or Ajax (XHR), so in this case you have to add setTransports(['websocket']) when creates the socket instance.
Try adding an options Map when you initialize your socket.
This is just a different way of doing the same thing from the example in pub.dev.
io.Socket socket = io.io("http://192.168.1.14:5000", <String, dynamic>{
"transports": ["websocket"],
});
On one of my projects I can confirm that it doesn't work without this being passed in.

Related

Stream interactive shell session with socket.io

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 👍

how can i include a socket.io-client in the service worker of chrome Extension(manifest V3)

I copied the client socket.io script from the cdn and then used importScript but when i tru to run it gives
ReferenceError: document is not defined
at JSONPPolling.doPoll (socketio.js:3683)
at JSONPPolling.poll (socketio.js:4369)
at JSONPPolling.doOpen (socketio.js:4313)
at JSONPPolling.open (socketio.js:3399)
at Socket.open (socketio.js:2796)
at new Socket (socketio.js:2725)
at socketio.js:2560
at Manager.open (socketio.js:470)
at new Manager (socketio.js:383)
at lookup (socketio.js:220)
How can i solve this, my code for the service worker file is
try {
importScripts('socket/socketio.js')
const socket = io("http://localhost:8080")
socket.on('connect', () => {
console.log(socket.id)
})
} catch (e) {
console.log(e)
}
For me {jsonp: false} did omit the document error, but didn't get connected to my server.
try using { transports: ['websocket'] } as options in socket.io connection
service_worker.js
const socket = io('http://localhost:9000', { transports: ['websocket'] });
In my node server
const io = require('socket.io')(server, {cors: '*'})
This works for me! : )
You can use the webpack to bundle the socket.io client into the background service worker.
To avoid the document issue mentioned by wOxxOm you can use jsonp: false option.
const socket = io('URL', {
jsonp: false,
});

Whats the problem with the socketio connection?

Im having this alot of http petitions (6k INSIDE LAGGING) in 1-3 minutes in the console when i receive or send data to a socketio connection.
Im using node+express in the backend and vue on the front
Backend:
app.js
mongoose.connect('mongodb://localhost/app',{useNewUrlParser:true,useFindAndModify:false})
.then(result =>{
const server = app.listen(3000)
const io = require('./sockets/socket').init(server)
io.on('connection', socket =>{
// console.log('client connected')
})
if(result){console.log('express & mongo running');
}
})
.catch(error => console.log(error))
I created a io instance to use it on the routes
let io
module.exports = {
init: httpServer => {
io = require('socket.io')(httpServer)
return io;
},
getIo:()=>{
if(!io){
throw new Error('socket io not initialized')
}
return io;
}
}
Then, on the route, depending of the logic, the if,else choose what type socket response do
router.post('/post/voteup',checkAuthentication, async (req,res)=>{
//some logic
if(a.length <= 0){
io.getIo().emit('xxx', {action:'cleanAll'})
}
else if(b.length <= 0){
io.getIo().emit('xxx', {action:'cleanT',datoOne})
}
else{
io.getIo().emit('xxx', {action:'cleanX',dataTwo,dataOne,selected})
}
res.json({ serverResponse:'success'})
})
In the front (component) (activated with beforeUpdate life cycle hook)
getData(){
let socket = openSocket('http://localhost:3000')
socket.on('xxx', data => {
if(data.action === 'cleanX'){
if(this.selected === data.selected){
this.ddd = data.dataTwo
}
else if(!this.userTeamNickname){
this.qqq= data.dataOne
}
}
else if(data.action === 'cleanAll'){
this.ddd= []
this.qqq= []
}
else if(data.action === 'cleanT'){
this.ddd= data.dataOne
}
})
},
1. What kind of behavior can produce this such error?
2. Is any other most efficient way to do this?
It looks like socket.io is failing to establish a webSocket connection and has never advanced out of polling. By default, a socket.io connection starts with http polling and after a bit of negotiation with the server, it attempts to establish a webSocket connection. If that succeeds, it stops doing the polling and uses only the webSocket connection. If the the webSocket connection fails, it just keeps doing the polling.
Here are some reasons that can happen:
You have a mismatched version of socket.io in client and server.
You have some piece of infrastructure (proxy, firewall, load balancer, etc...) in between client and server that is not letting webSocket connections through.
You've attached more than one socket.io server handler to the same web server. You can't do that as the communication will get really messed up as multiple server handlers try to respond to the same client.
As a test, you could force the client to connect only with webSocket (no polling at all to start) and see if the connection fails:
let socket = io(yourURL, {transports: ["websocket"]})'
socket.on('connect', () => {console.log("connected"});
socket.on('connect_error', (e) => {console.log("connect error: ", e});
socket.on('connect_timeout', (e) => {console.log("connect timeout: ", e});

socket io and mqtt nodejs duplicate entry

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?

Node.js - Socket.io-client does not emit data

I'm trying to build a simple socket.io-client using nodejs, but I'm facing a trouble...
I'm connecting with the socket.io (server), but I can't emit any data. Follow bellow my simple code:
Client Side:
var socketIO = require('socket.io-client')('http://serverdns:3000');
socketIO.on("dashboard", (data) => {
console.log(data);
});
socketIO.on('connect', function(){
console.log("Connected with the translator service.");
socketIO.emit('dashboard', 'teste');
});
socketIO.on('disconnect', function(){
console.log("Disconnected from the translator service");
});
socketIO.on('error', function(err){
console.log(err);
});
Socket.io version: 2.1.1 (I've tried to use old versions but the same problem happens).
The connect event works, the log "Connected with the translator service." is generated, but emit does not work.
Server side:
var server = require('http').createServer();
var ioServer = require('socket.io')(server, { pingInterval: 2000, pingTimeout: 60000, cookie: false });
class SocketServer {
constructor() {
var self = this;
ioServer.on('connection', function (client) {
console.log('[SOCKETIO] AVAILABLE');
client.on('main', self.main);
client.on('disconnect', self.disconnect);
});
server.listen(3000);
}
getSocket(){
return ioServer;
}
main(data) {
console.log(data);
}
disconnect() {
console.log("[SOCKETIO] DISCONNECTED");
}
}
module.exports = new SocketServer();
Anyone can help me?
Are there anything I'm not seeing?
Thanks a lot.
Right now you are emitting to the event dashboard from client. But on the server side you have no code that is handling that event. You are currently logging the event main which does not match with what you're emitting. Try client.on('dashboard', self.dashboard). Make your own dashboard function.

Resources