Socket.IO Can't emit message from serer to client - javascript

I have a connection with the server and client and have the server listening for a player to be made in the lobby. The server receives the player name and updates the player, however, when emitting the player back to the client I am having issues.
Simply, the pseudo-structure of our implementation follows as such...
Server
io.on('connection', function(socket){ ....
socket.emit('ack', {....
socket.on('createPlayer', function(data){
.... (update newPlayer object) .....
socket.emit('newPlayer', {
playerName: newPlayer.name
[...]
Client
let socket = io();
socket.on('ack', function(data) {
console.log('ack', data)
}
socket.on('newPlayer', function(data) {
console.log('newPlayer', data)
When a connection is made by the client's browser to the server, the 'ack' message is sent and received and logged to the client's console. But, When the client makes a new player and the 'createPlayer' socket.on is hit it tries to emit the new player back to the client but is never received.
Any suggestions as to why the client would never receive the sent message?

You should use this for sending message to all connected clients:
io.emit('event_name', msg);
Also you should use this for all clients except new clients:
socket.broadcast.emit('event_name', msg);
This function is for sending message to new client that sent message at that time:
socket.emit('event_name', msg)
You can send specified client using this method:
io.to(socketId).emit('event_name', data)

Related

SSE/Redis - how to recover messages sent when SSE goes offline

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

How to Callback socket.io client using sails.sockets.js onconnect event?

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});
});
},

How to call a function from outside the object

I am trying to make a proxy between sockets and websockets. I receive requests on socket server and I want to proxy them to websocket clients, however websocket.ws.send appears to be undefined. What would be the correct way of doing this? How to call ws.send() from outside of the object?
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({port: 8001}),
var net = require('net')
websocket = wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('received: %s', message);
});
ws.send("NEW USER JOINED");
});
var socketServer = net.createServer(function(socket) {
socket.on("data", function(data){
console.log("Received: "+data)
websocket.ws.send("Message")
});
});
socketServer.listen(1337, '127.0.0.1');
The problem you have is that ws is a single web socket for one connection. It is not a property on the websocket object, but an argument to a callback you define. Each time someone connects you will get a connection event which will execute your callback, allowing you to bind a function to that specific web socket for the message event.
You either need to store the ws object in a variable that the socket server can access or you could broadcast to all clients.
wss.clients.forEach(function each(client) {
client.send(data);
});
This will work fine if you only have one client, however if you have multiple connections to both the websocket and socket server then you need to use a method of identifying connections on both so that you can locate the websocket connection you need to send data to.

Socket.IO: Reconnect Causes Server Connect Code to Run Twice

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.

Reconnection in socket.io problem in `socket.on('message',function(){})`

I have a socket.io connection to connect to server and client,
It work fine.
Now when I try to reconnect it on disconnect from server it get connected but then socket.on('message' doesnt get fired any more.
I checked it from server side it is pushing that message.
Please suggest me some thing I am out of ideas now.
I am sure that problem is on client side socket.on message
Client side code
var socket = new io.Socket('some host name',{port:80,rememberTransport:true});
socket.on('connect', function(){
clearInterval(socketInterval);
});
socket.on('message', function(obj)
{
alert("meg from server");
});
socket.on('disconnect', function()
{
socketInterval=setInterval("socket.connect()",5000);
});
socket.connect();
I don't know node.js, but it looks like syntax error, haven't you forgot the right paratheses?
socket.on('connect', function(){
clearInterval(socketInterval);
});
socket.on('message', function(obj)
{
alert("meg from server");
});
socket.on('disconnect', function()
{
socketInterval=setInterval("socket.connect()",5000);
});
it would appear that the "problem" most likely is on the server side. The server has two ways to send messages to the client (emit and broadcast). If you are doing a one to one message, most people use emit. I am assuming that you built a chat server which stores the sessionIds of the client. It works fine with the initial connection because the server has the correct sessionId, but let's say connection is lost and you reestablish connection, now the server tries to send a message to the client. If your server stored the initial sessionId, say in an array, and attempts to use the original sessionId to emit a message, it will fail because reconnection causes a new sessionId to be created.
The solution in this case is to remove the previous sessionId from the array and add the new sessionId upon reconnection.

Categories