Skip to content Skip to sidebar Skip to footer

Websockets: Send Messages And Notifications To All Clients Except Sender

I am developing chat based on websockets and webrtc. I would like to send messages to all connected users except sender but I cannot find suitable solution. To be more specific, I

Solution 1:

Here is a very simple way of sending to everyone connected except the sender.

Create a broadcast function on your webSocketServer instance that will take two params.

...
var webSocketServer = new WebSocketServer.Server({ port: 8081 });
...
/*
 * method: broadcast
 * @data: the data you wanna send
 * @sender: which client/ws/socket is sending
 */
webSocketServer.broadcast = function(data, sender) {
  webSocketServer.clients.forEach(function(client) {
    if (client !== sender) {
      client.send(data)
    }
  })
}

...
// On your message callback.
ws.on('message', function(message) {
 ...
  // Note that we're passing the (ws) here
  webSocketServer.broadcast(message, ws);
})

That's it, the broadcast method will send to each connected client except the one who is sending.


Solution 2:

Ok, so we are now storing the CLIENTS in a way that allows us to uniquely identify each client that is connecting, and store arbitrary information about them for later retrieval.

The code below will send the "notes" message to all clients, and THEN add the newly connecting client to the "all clients" list.

SERVER.JS:

var http = require('http'),
    Static = require('node-static'),
    WebSocketServer = new require('ws'),

    // list of users
    /*
        We are now storing client data like this:

        CLIENTS = {

            uniqueRandomClientID: {

                socket: {},         // The socket that this client is connected on
                clientDetails: {    // Any details you might wish to store about this client

                    username: "",
                    etc: "etc"
                }
            }
        };

        So now to get at the socket for a client, it'll be: CLIENTS[uniqueRandomClientID].socket.
        Or to show a client's username, it'll be: CLIENTS[uniqueRandomClientID].clientDetails.username.
        You might want to write a 'getClientByUsername' function that iterates the CLIENTS array and returns the client with that username.
    */
    CLIENTS = {},

    // web server is using 8081 port
    webSocketServer = new WebSocketServer.Server({ port: 8081 });

// check if connection is established
webSocketServer.on('connection', function(ws) {

    console.log('connection is established');

    // Now using a randomly generated ID to reference a client. Probably should be better than Math.random :D
    var wsID = Math.floor(Math.random() * 1000);

    ws.on('message', function(message) {

        console.log('received: %s', message);
        var received = JSON.parse(message);

        if(received.type == "login"){

            // If a client with this login name doesnt exist already, its a new client
            if(!CLIENTS[wsID]) {

                doBroadcast(
                    {
                        "newuser": received.name,
                        type: "notes"
                    }
                );

                // Now add this new client to the list
                CLIENTS[wsID] = {

                    socket: ws,
                    clientDetails: {

                        username: received.name
                    }
                };
            }
        } else if(received.type == "message") {

            doBroadcast(message); // broadcast messages to everyone including sender
        }
    });

    ws.on('close', function(_event) {

        if(CLIENTS[wsID]) {

            console.log('user ' + CLIENTS[wsID].clientDetails.username + ' left chat');
            delete CLIENTS[wsID];
        }
    });

    /*
    * Added this to 'catch' errors rather than just red dump to console. I've never actually done anything with this myself (I *like* red text in my console), but I know this handler should be here :P
    */
    ws.on('error', function(_error) {

        console.log("error!");
        console.log(_error);
    });

    /*
    * Send an object to a client
    *
    * @param WebSocketClient _to - The client you want to send to (generally an index in the CLIENTS array, i.e CLIENTS["bobsusername123"]
    * @param Object _message - A stringifyable JSON object. Complex ones can screw things up, but your basic key/value pairs are usually fine to send.
    */
    function doSend(_to, _message) {

        _to.send(JSON.stringify(_message));
    };

    // Added broadcast function to replace sendAll
    // Notice how it JSON stringifies the data before sending
    /*
    * Broadcast a message to all clients
    *
    * @param Object _message - A stringifyable JSON object. Complex ones can screw things up, but your basic key/value pairs are usually fine to send.
    */
    function doBroadcast(_message) {

        for(var client in CLIENTS) {

            if(!CLIENTS.hasOwnProperty(client)) continue;

            doSend(CLIENTS[client].socket, _message);
        }
    };
});

var fileServer = new Static.Server('.');
http.createServer(function (req, res) {

    fileServer.server(req, res);

}).listen(8080, function(){
    console.log("Server is listening 8080 port.");
});

console.log("Server is running on 8080 and 8081 ports");

MY CLIENT.JS (for your reference):

var loginButton = document.getElementById("loginbutton"),
    usernameInput = document.getElementById("usernameInput");

var SocketClient = function(_uri, _callbacks) {

    this.uri = _uri;
    this.callbacks = _callbacks;
};

SocketClient.prototype = {

    send: function(_message) {

        this.socket.send(_message);
    },

    connect: function() {

        try {

            this.socket = new WebSocket("ws://" + this.uri);
        } catch(e) { return false; }

        for(var callback in this.callbacks) {

            if(!this.callbacks.hasOwnProperty(callback)) continue;
            this.socket["on" + callback] = this.callbacks[callback];
        }

        return true;
    }
};

var socketClient = new SocketClient(

    "127.0.0.1:8081",
    {
        open: function() {

            console.log("connected.");
        },
        message: function(_message) {

            console.log("received data:");
            console.log(_message);
        },
        close: function() {

            console.log("closed.");
        },
        error: function(_error) {

            console.log("error: ");
            console.log(_error);
        }
    }
);

socketClient.connect();

loginButton.addEventListener("click", function(){

    name = usernameInput.value;

    if(name.length > 0){

        socketClient.send(JSON.stringify({
            type: "login",
            name: name
        }));
    }

});

AND THE CLIENT.HTML TO GO WITH IT:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8"/>
    </head>
    <body>
        <input type="text" id="usernameInput"/>
        <button type="button" id="loginbutton">Login</button>
        <script src="client.js"></script>
    </body>
</html>

Ive tested this with NWJS v0.12.3 running the server and Firefox on the client.


Solution 3:

This should work

const WebSocket = require('ws');

// Websocket variables
const wss = new WebSocket.Server({
    port: 3000
});
console.log('Websocket active on port 3000...');


// New WebSocket Connection
wss.on('connection', function connection(ws) {

    console.log('new connection')

    // On Message Received
    ws.on('message', function incoming(message) {

        console.log(message)
        
        // Send To Everyone Except Sender
        wss.clients.forEach(function(client) {
            if (client !== ws) client.send(message);
        });

    });


});

Post a Comment for "Websockets: Send Messages And Notifications To All Clients Except Sender"