I need to update some client side stuff if a user has a socket connection.
Currently I am broadcasting to everyone when a user connects he is "logged in"
Client side (could do it server side and get the same result)
// announce to everyone the user is online
socket.on('connect', function() {
socket.emit('im online');
});
Server side
io.sockets.on('connection', function (socket) {
socket.on("im online", function (data) {
// announce the online status of a new user
socket.broadcast.emit('connected user', {"name": socket.handshake.headers.user.username});
});
});
The problem is, now I load the page I let everyone know I am "online" because that loading of the page triggers the event, but if I am idol and another user reloads his/her page nothing is triggered on my end, so there is no indication I am online.
So I am thinking server side I can just capture an array of all the users who made it to the connection and send that array down to any new clients connecting and use that to compare to the users friend list to see if any username matches (usernames are 100% unique in each case BTW)
Then when a user disconnects I can just remove it from the array and let the client know.
This would be my solution, but it seems highly ineffective and I am hoping there is a better solution.
You could easily broadcast the disconnect events as well:
socket.on("disconnect", function (data) {
// announce the offline status of a new user
socket.broadcast.emit('disconnected user', {"name": socket.handshake.headers.user.username});
});
Th disconnect event is automatically generated on server side when the client disconnects.
On the other hand probably you have to store on server side all the connected users, because otherwise the newly connected users wouldn't be notified about the already connected others.
Related
I am wondering if this is the correct way to go about securing a socket.io room. Currently these are the steps that I am taking to ensure a user ends up in a private room, now I need to make sure the user gets authenticated before he is able to join.
A client connects to my socket.io server by calling io.connect and passing along the room he wants to join.
Client will be subscribed to the room and waits for emit of a message.
socket_write sends a json_encoded object to my server which holds a data property and the room to which this data will be sent.
My server receives the data through socket.on and emits the data to the given room where the client is listening.
The client will receive the proper information meant for him only.
My client code:
var socket = io.connect('http://localhost:8000');
socket.on('connect', function() {
socket.emit('room', window.location.href);
});
The server:
const server = net.createServer((socket) => {
// The event that fires on PHP's socket_write.
socket.on('data', (msg) => {
const data = JSON.parse(msg);
io.sockets.in(data.room).emit('log', data.html.toString().trim());
});
}).listen(5600);
The on connection event of my server:
io.on('connection', function (socket) {
// A client will trigger this event and pass their window.location.href(room) as room identifier.
socket.on('room', function(room) {
socket.join(room);
});
});
How I write to my socket.io server:
$data = [
'html' => 'test',
'room' => 'http://app.dev/stephan-v/app-test'
];
$json = json_encode($data);
socket_write($this->socket, $json, strlen($json));
This is my implementation of a private websocket message but of course this is not secure. If somebody knows the name of the room that person could easily listen in on the emitted messages.
Since the socket.join can only take place on my server I guess the only place to authentication is at that point?
So instead of simply passing along the room I guess I should also pass in data to authenticate the user. And at that point make an AJAX requests from my node server to my PHP backend?
Obviously I do not want to send a plain password and username over the wire so I have been reading up on JSON web tokens. I guess you need to:
send a JWT to the node server at the point of connection(along with which room to join, which I am currently doing).
Make an AJAX requests from my node.js server to my PHP backend on an authentication route.
Only let the user join the room if that user gets authenticated.
Sorry for the long post but there are a lot of components involved in this so I am hoping someone could confirm this workflow and perhaps give me some tips/pointers.
I would prefer not to install something like Redis at the moment because although it is a nice bridge between the frontend/backend it feels like overkill right now and I would like to understand this all at a more basic level.
I'm running a node.js server. On my website I use different URLs for different pages. For instance:
mydomain.com/ -- Index
mydomain.com/register -- Register
mydomain.com/profile -- Profile
I am using socket.io to send chat messages and notifications to the client. However, whenever the user switches page or performs a POST-request the socket connection is disconnected and then reconnected.
I'm wondering what the complexity of socket.io's connect/disconnect functions are and wether it is durable that all clients reconnect their sockets each time they perform an action on my website? I've looked at the documentation for socket.io without finding the answer.
That's what I have found, but I would guess it would really depend on your code. If each page connects to the channel then the connection will be reestablished. I am also in the habit of storing messages on the server side to reestablish state - something to this effect:
const events = []
const onSomeEvent = function(myEvent) {
events.push(myEvent)
socket.emit("onSomeEvent", myEvent)
}
socket.on("connect", function(){
events.forEach(function(myEvent){
socket.emit("onSomeEvent", myEvent)
})
})
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.
So to clarify, I know the client should send a message such as 'join-room' to the server for handling, and thats fine, and I know I can do the same for 'leave-room'.
What I want is to actually listen to the events themself, because say if a client disconnects, I need to send a message to the rooms affected, as when a client disconnects then they automatically leave all rooms.
So I want something like;
socket.on('join' function() {
// send message
});
socket.on('leave' function() {
// send message
});
So that if the user closes the window (which disconnects the client, and then triggers all the rooms to be left) I can send a message out.
I am using the latest socket.io, with the redis adaptor.
Also;
What is the most efficient way to list all the rooms a particular socket is in, as technically I think the disconnect event should contain the client_id so I could do this manually.
The key thing is clarity and stability, although I am open to alternate approaches (must still use socket.io).
Thanks
So if I understood correctly your main question: you want to listen to the events of joining and leaving a room in the implementation itself such that
socket.join(room_id) should fire that event you want to listen to.
The thing is the docs dont mention any ways of listening to that event. In fact, the implementation itself shows no sign of firing an event when joining a room. My guess is that you will have to implement the join_room/leave_room system to handle that.
As for the sub-question, the socket object contains an array called rooms such that socket.rooms contains all the rooms the socket is currently in.
This is probably what you're looking for :
socket.on('disconnect', function() {
for(var room in socket.rooms) {
//do stuff before the client close the connection and leave the rooms
}
});
I'm trying to detect whether the websocket is running before allowing clients to connect to it. Consider the following code:
var socket = io.connect('1.1.1.1:1234');
socket.on('connect',function() {
console.log('Client has connected to the server');
});
socket.on('disconnect',function() {
console.log("The client has disconnected from the server");
});
How can I make sure that this block is only called if the server on that IP is actually running and how can I output a message to the users stating that the server is not up?
Thank you
You would need to fire the io.connect() atleast once (consider this as a ping) to detect if server is up, but you can then handle the failure to connect with the socket.on('connect_failed', function () {}) event handler and show a message to user that the 'server is down'. Have a look at Exposed Events for the client
Further, if you would want to reduce the number of times the reconnect is attempted, you can change the socket.io configuration setting for 'reconnect' to false. Checkout Socket.io Configuration for more details