I'm working on a chat app, and trying to listen to a socket io event on the client side, I used a useEffect with the socket as a dependency, but for some reason, when I open a new tab and send a message, (the socket changes) but the useEffect does not run.
const socket = io.connect("http://localhost:3001");
useEffect(() => {
console.log("useEffect:", socket.id);
socket.on("receive_message", (data: any) => {
console.log(data);
});
}, [socket]);
My server code:
io.on("connection", (socket) => {
socket.on("send_message", (data) => {
console.log("data: ", socket.id); // this logs
socket.emit("receive_message", data);
});
});
From what I understand, this works by the server listening in on an event called "send_message", this event is emitted from my client side, upon receiving this event, the server emits it's own event to the client side, and this is supposed to be picked up by the client side by running the useEffect every time the socket dependency changes, so why is my useEffect not running despite the dependency socket changing when I create a new tab?
Related
I have a simple snippet on the front end as follows which I can verify is working. I can do this by changing the port to something other than 3000 and it will error.
It is definitely finding the server at that port:
// Create WebSocket connection .. will error if I change the port
const socket = new WebSocket('ws://localhost:3000');
console.log('DEBUG: Web socket is up: ');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
I am using ws-express on the server side as follows. This was the minimal example given in the NPM docs:
const expressWs = require('express-ws')(app);
app.ws('/echo', (ws, req) => {
ws.on('message', (msg) => {
ws.send(msg);
});
});
However, the open event on the client never fires. I would like to send messages from the client to the server, but I assume, that I need an open event to fire first.
I am working on a social app and build chat module using socket.io. App is very complicated now and very difficult to debug. sometimes event not received. How I can figure out issue is frontend side or backend side without acknowledgement method because it tells the emitter socket event is listen by client or server. it not handle the case when client can't listen it as user is connected with socket. I confirmed this using server logs.
client.on('webrtc_offer', function (event) {
console.log("========= webrtc_offer : ", event)
event.uid = event.endUserId
event.endUserId = client.uuid
if (event.uid in users) {
console.log(`emiting webrtc_offer event to peer ${event.uid}`)
client.broadcast.to(users[event.uid]).emit('webrtc_offer_send', event);
client.emit('ringing', { callee: event.uid, caller_id: event.endUserId })
}
})
How i can confirmed that "webrtc_offer_send" event is emitted from server or not.? I am not interested it is listen in frontend or not it not my concern.
I have this scenario with socket.io:
I want to receive the data from a sever and Forward the data to webclient.But when I receive a lot of data and close the page, it console
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
DISCONNECTED FROM CLIENT
...(a lot)
Here is the code:
server:
var express=require('express');
var app=express();
var net=require('net');
var http=require('http').createServer(app);
var io=require('socket.io')(http);
var net=require('net');
var nodeServer = new net.Socket();
var aSocket=null;
io.on('connection', function (socketIO) {
aSocket=socketIO;
};
nodeServer.on('data', function(data) {
if(aSocket!=null){
aSocket.emit('pushToWebClient',useData);
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
}
client:
socket.on('pushToWebClient', function (useData) {
});
I find
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
console a lot of'DISCONNECTED FROM CLIENT' but actually it should console just once in the code.
I had even console.log(aSocket.id),it console just only one.
I don't know why it is console so many times.
I haved used setMaxListeners(10) to try to avoid it .
Will it lead to a memory leak?
It appears that you are registering multiple event listeners for the same disconnect event. In this code:
nodeServer.on('data', function(data) {
if(aSocket!=null){
aSocket.emit('pushToWebClient',useData);
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
}
You appear to be registering a new disconnect event listener every time you get a data message. So, if you have multiple listeners, then each one will get called when the socket disconnects and the result is that you will log the same message multiple times all for the same socket.
You can verify this is what is happening by moving your disconnect handler into the connection handler so it is only ever attached just once for each socket.
In addition putting asocket into a global or module-level variable means that your server code would only ever work with one single client at a time. It is not clear exactly what you are trying to do when you get data on the nodeserver connection - whether you're trying to send that data to only one specific client or to all connected clients.
I try to delete the code:
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
or moving it out of nodeServer handler,
it turn into normal and never suggest me to setMaxlisener.
I think maybe it is incorrect put one API into a API
And the envent maybe not release the socket,so it console multiple times .
EDIT: I'm moving this to the top because I saw that someone already provided my solution but you were having a problem managing the data sent to the client. Your aSocket variable will be overwritten by every new client that connects to your app. If you want to send data to a specific client using your server nodeServer, you should create a global variable (an array) that keeps track of all of your client socket connections. So instead of using one global variable aSocket do the following:
var net=require('net');
var nodeServer = new net.Socket();
var clients = [];
io.on('connection', function (socketIO) {
clients.push(socketIO);
var clientNum = clients.length-1;
aSocket.on('disconnect', function () {
clients.splice(clientNum, 1);
console.log('DISCONNECTED FROM CLIENT: '+socketIO.id);
});
};
nodeServer.on('data', function(data) {
//have your data object contain an identifier for the client that caused the handler to fire
//for the sake of the answer I just use data.id
var clientID = data.id;
if(clients[clientID]!=null){
clients[clientID].emit('pushToWebClient', useData);
}
}
Let me know how it goes! My original answer is below:
Try moving
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
out of your nodeServer.on('data', ...) event listener into the io.on('connection', ...) event listener like so:
io.on('connection', function (socketIO) {
aSocket=socketIO;
aSocket.on('disconnect', function () {
console.log('DISCONNECTED FROM CLIENT');
});
};
socket.io is designed to keep polling for the presence of the server/client. If either the server or the client are disconnected, the remaining 'side' continues to receive polling requests and, consequently, will continuously print an error.
You can see this effect on the client side in your browser when you disconnect your server and leave the client page open. If you look at the browser's error/console log what you should see is a continuous stream of net::ERR_CONNECTION_REFUSED errors. By placing the disconnect event handler in the .on('data', ...) handler for your server, you are seeing the converse of this situation.
net:ERR_CONNECTION_REFUSED example
This is basic code for socket.io
The following example attaches socket.io to a plain Node.JS HTTP
server listening on port 3000.
var server = require('http').createServer();
var io = require('socket.io')(server);
io.on('connection', function(client){
client.on('event', function(data){});
client.on('disconnect', function(){});
});
server.listen(3000);
I think, you should try.
Am not able to call socket-client listener using sails.sockets.js onConnect event on server side..
E.g
onConnect: function(session, socket) {
socket.on('chat message', function(msg){
console.log(msg);
console.log("socket.id: " + socket.id);
sails.sockets.broadcast(socket.id, 'chat message', {msg:msg});
});
}
Please let me know whats the correct way of calling back to your socket-client using socket-server events like onConnect..
If you are using standard sails.js socket library:
$(document).ready(function() {
io.socket.on('connect', function() {
});
io.socket.on('chat message', function(data) {
io.socket.post('/routeToAction', {
}, function(data, jwres) {
});
});
});
for newer version, you have to use config/bootstrap.js file for listen events
module.exports.bootstrap = function(cb) {
// handle connect socket first event executes after logged in
sails.io.on('connect', function (socket){
// store facebook token here
});
// handle custom listener for other stuff
sails.io.on('doSomeStuff', function (socket){
// check facebook token match with requested token
});
cb();
};
client : you can simple emit "doSomeStuff" after logged in with facebook and pass token with each request
Finally am become little expert in web sockets who knows back anf forth of push technoligy via websockets..
How to start with websockets :
Step 1: Choose any websocket framework for your application and install socket client on client side and socker server on server side with listeners(imp.).
Step 2: Once you are ready with socket setup on both sides then your client/browser will make a connection after every page load which is listened on server side via onConnect listener or event.
Step 3: Successfull connection on both sides giving you socket object which contains each client socket id which is managed at server side to either join any channel/room or just to make a broadcast or blast.
Remember:
i. Socket object is responsible for defining listeners on both client side and server side. Using socket object you can pass any data to listeners.
ii. Socket connection is very helpful when you trying to push data from client to server and vice-versa.
iii. You can make your small chatter tool with it once you understand as mentioned above.
Will share similar working snippet soon..
//onConnect event on server side
onConnect: function(session, socket) {
console.log("Socket Connect Successfully: " + socket.id );
socket.on('chatAgency', function(data){
sails.sockets.broadcast(data.agencyId,"chatAgency", {message:data.message,agencyId:session.agencyId});
});
},
I have a very simple socket.io connection. My server does the following:
io.sockets.on("connection", function (socket) {
console.log("CONNECTED ON SERVER");
socket.emit("connected", "CONNECTED!");
});
Indeed, the client gets the "CONNECTED!" message.
I need to be able to detect when a client disconnects and take some action. I've tried:
io.sockets.on("disconnect", function (socket) {
console.log("DISCONNECTED!");
});
...but this does not log "DISCONNECTED!" on the server. However, CONNECTED ON SERVER from above does get logged.
I know that the socket can detect the disconnect because once I close the browser window, the server logs out:
info - transport end (socket end)
debug - set close timeout for client
debug - cleared close timeout for client
debug - cleared heartbeat interval for client
debug - discarding transport
This means that socket.io is able to detect that the client connection closed. How can I detect that it was closed?
You have to set the event on each socket itself
You can see on their how to use page they set the disconnect event on the actual socket:
// note, io.listen(<port>) will create a http server for you
var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
io.sockets.emit('this', { will: 'be received by everyone'});
socket.on('private message', function (from, msg) {
console.log('I received a private message by ', from, ' saying ', msg);
});
socket.on('disconnect', function () {
io.sockets.emit('user disconnected');
});
});
If you take a look in the socket.io code (of at least v0.10.20) you will see that io.sockets is a SocketNamespace object (from namespace.js), and in that is the handlePacket function
the connection packet does
self.$emit('connection', socket);
Which will send the event to its own EventEmitter stuff.
Where as the disconnect packet is done this way:
socket.$emit('disconnect', packet.reason || 'packet');
So the disconnect event is never fired for the namespace object.
The current github code shows that they have moved the packet handling to their respective classes
connection emission in namespace.js Line 172
// fire user-set events
self.emit('connect', socket);
self.emit('connection', socket);
disconnect emission in socket.js Line 370
...
this.disconnected = true;
delete this.nsp.connected[this.id];
this.emit('disconnect', reason);
};