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.
Related
On a website I have a very simple Live chat setup that uses SSE/Redis and pub/sub structure.
The basic setup (without going into details) is:
Client-side using EventSource
Opens SSE connection and subscribes to live events sent by SSE daemon. Sends messages to an API endpoint
connect(hash, eventListener) {
const url = `${url}?client=$hash=${hash}`;
sseSource = new EventSource(url);
sseSource.onopen = function(e) {
reconnectFrequencySeconds = 1;
}
sseSource.onerror = err => {
this.closeSSEStream();
this.reconnectSSEStream(hash, eventListener);
};
sseSource.addEventListener('messages', event => {
const messages = JSON.parse(event.data);
eventListener(messages);
});
},
API endpoint
That stores message in the database and pushes it to a Redis channel.
Redis DB
That keeps and serves the messages.
Server-side SSE daemon
Subscribes client to a channel in a Redis DB and forwards messages to the subscribers using SSE stream.
const subscriber = redis.createClient();
subscriber.select(config.redisDatabase);
subscriber.on('message', function (channel, message) {
log(connectionId, 'Redis: new msg on channel: ' + channel, message);
let event = {
event: 'messages',
data: message
};
currentClient.connection.write(event);
});
The whole thing works pretty well, however, it is one tweak away from perfection.
During deploy we restart our workers (including SSE daemon) and while it goes offline users do not receive LIVE updates. It reconnects just fine but messages that have been sent during down time are lost (as daemon starts listening to messages on reconnect only).
My only idea for a workaround involves an overengineered solution where "lost" messages are collected with a separate API endpoint on reconnect and displayed to the user.
Is there an out-of-the-box way to receive messages that have been stored to Redis BEFORE subscribing to a channel? E.g. "pop" unprocessed messages or something like that?
when you have reconnected send request to check if you are new msg with time of last msg
and if you are newer msg send it in result msg to avoid new request
I followed a different S/O answer to figure out how to communicate to my server that a client disconnected by using
var socket = io.connect(<your_url>, {
'sync disconnect on unload': true });
The problem is, since this is part of the original socket configuration, I can't tell from the server which of my clients actually disconnected. On my client-side, I display a list of usernames for all connected clients, so I need to know which username to remove from that list for the remaining clients.
server-side code that gets triggered when a client closes out is:
socket.on('disconnect', reason => {
console.log('user disconnected', reason);
});
but the "reason" variable turns out to just be a string that says: "transport close" with no information about the actual client that disconnected.
One approach I thought of was, whenever a client disconnects, the server can request a response from all connected clients and use that to send out an updated list every time, but this seems excessive. I'd much prefer to know which client disconnected when they disconnect, and simply broadcast the id of the newly disconnected client, so the other clients are able to update their respective user lists locally. When a new client joins, after all, I broadcast that client's username, so all clients can update locally - I'd like to use the same pattern when a client disconnects.
In short, does anyone know a way to, within the "sync disconnect on unload" configuration of socket.io, also send the client's ID on unload?
Turns out I needed to keep an array in the server of active participants, adding to it every time they connect.
let users = []
socket.on('join', data => {
data.id === socket.id
users.push(data)
})
socket.on('disconnect', reason => {
let user = users.find(u => u.id === socket.id)
// we emit an event from the server, not from a particular socket
io.emit('player disconnected', {
user
}
})
I have a simple TCP client. It makes a connection to a local data processing server. Sometimes the server will not be running, and that is ok. If it cannot connect, I would like it to fail gracefully with perhaps some console output, but not crash my process.
here is the code:
class EngineSwitchboard {
static routePacket(packet) {
if (gpsPackets.includes(packet.packetId)){
const gpsClient = new net.Socket();
gpsClient.connect(9998, 'localhost', function() {
gpsClient.write(JSON.stringify(packet));
})
}
}
}
I have tried to wrap it in a try-catch but it still crashes out the calling process with Error: connect ECONNREFUSED 127.0.0.1:9998
thanks for any help
You can listen to the socket's on error event handler.
gpsClient.on('error', function(){})
The above one is a much generic event handler. If you want to handle specific errors. You can go through the list available and use the appropriate one
https://socket.io/docs/client-api/#Event-%E2%80%98connect%E2%80%99
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});
});
},
Whenever I disconnect using socket.disconnect(); and then reconnect using socket.connect();, the server runs my handshake code twice. The strange thing is, even though the server connection code runs twice, there is only one connection in my array after reconnecting. This happens on an accidental disconnection, intentional, or even if the server restarts. Bit of code:
io.on('connection', OnConnect);
function OnConnect(socket) {
var connection = { socket: socket, realIp: ip, token: GenerateConnToken() };
connections.push(connection);
console.log('Connected');
// Client will respond to this by emitting "client-send-info".
// This is emitted once on initial connect, but twice on reconnect.
socket.emit('acknowledge', connection.token);
socket.on('client-send-info', function() {
console.log('Client Sent Info');
});
socket.on('disconnect', function() {
console.log('Disconnected');
});
}
The above code, when a client connects, disconnects, and then reconnects once, will produce the following log:
Connected
Client Sent Info
Disconnected
Connected
Client Sent Info
Client Sent Info
Why is it that, when reconnecting, the connection code will run twice, but only create one connection object?
EDIT: Upon further inspection, it seems that a different piece of my connection code is being performed twice when the client reconnects. The above code is updated to reflect the relevant information.
Strangely, the solution is completely client side. Instead of the following code:
var socket = io.connect();
socket.on('connect' function() {
socket.on('acknowledge', function() {
});
});
You have to use:
var socket = io.connect();
socket.on('connect' function() {
});
socket.on('acknowledge', function() {
});
Otherwise, the server will appear to be sending multiple emits when it is in reality only sending one, and it's the client that falsely receives multiples. With the second code format, the client successfully connects initially, disconnects, and reconnects without receiving multiple emits.
Simply, don't put any additional socket.on('x') calls inside the on('connection') call. Leave them all outside it.