How to send old messages with Websockets - javascript

I've got a working Websockets example, where clients receive messages from the server.
I'm not sure how I should send old messages to clients when they connect.
Example:
Each client supplies their name when they connect
The server responds with "[name] just connected" (to all clients)
Any new clients would NOT get these messages
I'm wondering if there's any way clients can receive old messages (either all of them, or messages in the last 5 minutes would be acceptable).
I suspect I may have to capture this information myself, store it somewhere (like a database) and send the messages to new clients myself. Is that right, or am I missing something?
If anyone has pseudo code, or a link to an example of how others have implemented this, that would be handy.

You could do something like this:
Each message should have an id -> muid (Message Unique ID)
Each time a client send s a message, it gets an ACK from the server along with the muid for the sent message.
Each time a new message is received in the server side, a muid is assigned, sent with the ACK and also sent with the message to every connected user. This way the view will be able to present, for every user, the same sequence at some point in the time.
Each time a new user connects it sends the last muid it has received so the server knows where this user stopped receiving messages. The server could then send as many old messages as you want, depending on the kind of storage you implement:
Full history: I would recommend a database storage with proper indexing
Last N messages: Depending on the size of N you could simply store the last N messages in a fixed size Array and send them, all or the needed chunk, on each reconnection. Keep in mind that this will consume memory so, storing last 1024 messages for 1024 different chats would eat quite a bit of memory, specially if messages are of unlimited size.
Hope it helps

You will have to capture it by your own and store it on server... once user connects you will have to name that data to all connected clients and the messages which you have stored back to the user who has connected. So, you will have to code to broadcast the data to users
By the way what are you using server side? (Node, Erlang , etc)
You can check following link if you are using node.js
http://martinsikora.com/nodejs-and-websocket-simple-chat-tutorial

Related

Is it possible to make a notification using geolocation as a condition?

Example:
Schedule a notification for 15 minutes and save the user's location.
If the user leaves radius, the notification will not be sent.
Would it be possible to do this using onesignal or just with cordovaLocalNotification?
var notificationObj = {
contents: {
en: "asdasdasd"
},
include_player_ids: [playerId],
send_after: "2017-02-15 20:42:00 GMT-0200",
}
window.plugins.OneSignal.postNotification(notificationObj,
function(successResponse) {
console.log("Notification Post Success:", successResponse);
},
function (failedResponse) {
console.log("Notification Post Failed: ", failedResponse);
alert("Notification Post Failed:\n" + JSON.stringify(failedResponse));
}
)
})
Before that I would save the current location and at the time of sending I would compare if the location is within the 1km radius. If yes, I would send it if not, I would not send
There are two types of notifications: local notifications and push notifications.
Local notifications work like an alert (i.e. I want to be awaked at 9AM) and they can be saved and launched locally, without any internet connection, at the specified time. For this kind of notifications, you can use the Local Notifications plugin.
The second case, Push Notifications, are sent (basically...) from your server to the user app via internet suitably a kind of notification rules set server side.
So, for you specific case, if I got your needs, you can:
get your actual location and timing, send all these data to your server
save (server side) these data and set a timing (15 mins) to send a push notification
after 15 mins, without info from the client app, send the push notitication.
If the user leave the circle radius, send a message to your server, telling "I'm out of the circle, don't send me the push notification". You can decide, server side, to stop the further notification sending.
So, for your case, I would just use Push Notifications.
Little drawback: if the user looses connection and leaves the circle, the client message would not be sent to the server and the server would not be alerted about that, so it'll send the notification to the user. Anyway you can manage, client side, this case to avoid it.
Edit: you can also manage everything using Local Notifications as alerts and don't use Push Notifications at all, as you wish. I would not use both systems.

Can Socket.io emits arrive out of order? What if volatile?

I've been looking around for a definitive answer to this but I seem to keep finding contradictory answers (ex this and this).
Basically, if I
socket.emit('game_update', {n: 1});
from a node.js server and then, 20 ms later,
socket.emit('game_update', {n: 2});
from the same server, is there any way that the n:2 message arrives before the n:1 message? In other words, does the n:1 message "block" the receiving of the n:2 message if the n:1 message somehow got lost on the way?
What if they were volatile emits? My understanding is that the n:1 message wouldn't block the n:2 message -- if the n:1 message got dropped, the n:2 message would still be received whenever it arrived.
Background: I'm building a node.js game server and want to better understand how my game updates are traveling. I'm using volatile emit right now and I would like to increase the server's tick rate, but I want to make sure that independent game updates wouldn't block each other. I would rather the client receive an update every 30 ms with a few dropped updates scattered here and there than have the client receive an update, receive nothing for 200 ms, and then receive 6 more updates all at once.
Disclaimer: I'm not completely familiar with the internals of socket.io.
is there any way that the n:2 message arrives before the n:1 message?
It depends on the transport that you're using. For the polling transport, I think it's fair to say that it's perfectly possible for messages to arrive out-of-order, because each message can arrive over a different connection.
With the websocket transport, which maintains a persistent connection, the message order is reasonably guaranteed.
What if they were volatile emits?
With volatile emits, all bets are off, it's fire-and-forget. I think that in normal situations, the server will wait (and queue up messages) for a client to be ready to receive messages, unless those messages are volatile, in which case the server will just drop them.
From what you're saying, I think that volatile emits are what you want, although once a websocket connection has been established I don't think you'll see the described scenario ("receive an update, receive nothing for 200 ms, and then receive 6 more updates all at once") is likely to happen. Perhaps only when the connection gets lost and is re-established.
The answer is yes it can possibly arrive later, but it is highly unlikely given that sockets are by nature persistent connections and reliability of order is all but guaranteed.
According to the Socket.io documentation messages will be discarded in the case that the client is not connected. This doesn't necessarily fit with your use case, however within the documentation itself it describes Volatile events as an interesting example if you need to send the position of a character.
// server-side
io.on("connection", (socket) => {
console.log("connect");
socket.on("ping", (count) => {
console.log(count);
});
});
// client-side
let count = 0;
setInterval(() => {
socket.volatile.emit("ping", ++count);
}, 1000);
If you restart the server, you will see in the console:
connect
1
2
3
4
# the server is restarted, the client automatically reconnects
connect
9
10
11
Without the volatile flag, you would see:
connect
1
2
3
4
# the server is restarted, the client automatically reconnects and sends its
buffered events
connect
5
6
7
8
9
10
11
Note: The documentation explicitly states that this will happen during a server restart, meaning that your connection to the client likely has to be lost in order for the volatile emits to be dropped.
I would say a good practice would be to write your emits as volatile just in case you do get a dropped client, however this will depend heavily on your game requirements.
As for the goal, I would recommend that you use client side prediction using some sort of dynamic time system or deltatime based on the client and server keeping a sync clock to help alleviate some of the problems you can incur. Here's an example of how you can do that, though I'm not a fan of the creators syntax, it can be easily adapted to your needs.
Hope this helps anyone who hits this topic.
Socket.io - Volatile events
Client Side Prediction

Node.js/Socket.io: Create a bot who's always in chat lobby/room, detecting specific activity and reporting to server?

I am running Node.js and Socket.io on Linux Server.
I've created an online chat room/lobby, I am wondering how can I create like a daemon who has a role of user, he is connected to lobby always and is monitoring lobby, and messages that users post. When specific criteria is matched - report back to server.
For example, some user posts too many messages per minute, the bot would send message to user saying to slow down, if user continues bot would send request to server saying to kick that user.
I am new to node.js and socket.io, so I am not sure how to implement it.
I don't want to hard code every rule or criteria into server itself.
I don't think your way will be working. The way on top of my head is doing it on server. Socket.io can fire any event on client side and send to server, so you can ask server to listen to certain event and handle your logics accordingly on server. Below is some sample code for your reference.
client side:
this event will fire whenever client sends a message.
$("#msgbutton").click(function(){
socket.emit("message","some message client send");
});
server side:
socket.on('message', function(msg){
var now = new Date();
var lastsent = socket.lastsent; //socket is an object and you can store lastsent datetime to it
var diff = now.getTime() - socket.lastsent.getTime();
if (diff/1000 > 2) // if message interval is larger than 2 seconds
{socket.to(room).emit('message',msg); // send message to whole room}
else if
{ // maybe send a warning event to user }
});
The code is not tested, and only consider the time difference between current msg and last message. If you want to monitor the message sent event over certain time course, you will have to write your logics on server to do that. Hope this can give you some pointers.

Socket.IO emit data into a room to myself

I'm building a chat application in which I want to load on start the last messages between 2 users.
Here's what I do on the frontend so load the old messageList from the database:
socket.emit('get messageList', data);
on the backend side I load the messages into messages and try to emit them back. I dont want to broadcast.emit since I want to load the data in my session, not in the chat partners.
socket.in(roomId).emit('send messageList', messages);
When I execute this code the messageList of the chat partner gets refreshed. Basically it has the same effect as
socket.in(roomId).broadcast.emit('send messageList', messages);
Before I implemented the rooms a normal
socket.emit('send messageList', messages);
would update my list just as I'd expected. But since I use the code with rooms it doesn't work anymore.
My questions:
Why is that?
Is it possible to send back data from the backend to the client with socket.io?
Or am I doing something completely wrong?
socket.nsp.to(room).emit('room_message','hello world')
I'll make my comment into an answer since that seems to be what will work for you.
If you're just trying to respond to the client that send you a request, you just socket.emit() back to the requesting socket. You're just trying to respond to the sender so you don't do anything differently just because there are chat rooms being used. The response goes to the socket that asked for it, regardless of chat room usage.
To send to a single client, you just send to that client's socket. You only use chat rooms to help with the sending if you want to send to all clients in that room or all clients in the room except one.

Sending data to specific client and not to the whole channel

I am currently playing with Faye.js. Upon subscription to a channel I want that specific client to receive an object that would be irrelevant to anybody already in the channel.
How can this be achieved?
More detail:
The object is an array of the last 20 chat comments in the room. Anybody already in the room would have received this object already or been a part of the chats and so it is not required for these to receive it.
Thank you in advance.
The only way I've come across is to generate a client-side GUID. When the client connects, it announces itself to the others through a 'public' channel, you can then use the GUID to send messages directly to this client.
For example, take the piece of code from the answer of this previous question to generate something that looks like a UUID.
You can then do something on the client-side like this:
var guid = guidGenerator();
client.subscribe('/privChannel_' + guid, onPrivateMessage);
client.subscribe('/pubChannel', onPublicMessage);
client.publish('/announce', { 'myId': guid });
function onPrivateMessage() {
// do something
};
function onPublicMessage() {
// do something
};
Your server should always subscribe to the '/announce' channel, and when any message is posted in that channel it should store that id so that it can identify that particular client. Then, the server can use this id to publish to a channel only this client should be subscribed to.
Note however that this is not a good idea for sensitive data. Other clients could also subscribe to '/announce' and farm the guids for malicious purposes.

Categories