0

From the HTML file I am sending message using webSocket.

const socket = new WebSocket("ws://localhost:3000/{{ token }}");
socket.send(JSON.stringify(message));

token will come from browser URL.

server.js

const WebSocket = require('ws');
const qs = require('querystring');
const http = require('http');
const wss = new WebSocket.Server({ port: 3000 });
const webSockets = {};


wss.on('connection', function (ws, req)
{
    let url = req.url;
    let userToken = url.substring(url.lastIndexOf('/') + 1);
    webSockets[userToken] = ws;
    
    ws.on('message', function incoming(message)
    {
        let messageArray = JSON.parse(message);
        let token = messageArray['token'];
        let toUserWebSocket = webSockets[token];
        toUserWebSocket.send(message);

I have opened 3 browsers with following URL

`https://url/same_token`
`https://url/same_token`
`https://url/different_token`

Messages are being received in all browsers. If message is send from send_token I want message to be received only by browser with same_token

S S
  • 1,443
  • 2
  • 12
  • 42
  • Please review the [answer I linked you to](https://stackoverflow.com/a/19469286/1144627%5D). You have to bind ws to a token indexed array of clients, then you can send the message to the array of users `webSockets[userToken] = ws`. `var toUserWebSocket = webSockets[token]` `toUserWebSocket.send(message)` – Will B. Jun 20 '21 at 06:23
  • I tried that method already, it is also passing message to everyone – S S Jun 20 '21 at 14:43
  • I am not able to reproduce the issue. What does the client side code look like? Also what does `console.log(userToken)` and `console.log(token)` output? – Will B. Jun 20 '21 at 16:18

1 Answers1

1

I was not able to reproduce the issue as described, but was only able to receive the sent message to only one of the connected clients with the same token.

The issue with the single connected client is due to webSockets[userToken] = ws being referenced, as opposed to using an array of clients webSockets[userToken] = []; and webSockets[userToken].push(ws);

Also be sure that you do not have a zombie process of node server.js running in the background.

//...

const clients = {};

wss.on('connection', function connection(ws, req) {
    let id = req.url.substring(req.url.lastIndexOf('/') + 1);
    if ('' === id) {
        //connecting id is missing
        ws.terminate();

        return;
    }
    if ('undefined' === typeof clients[id]) {
        clients[id] = [];
    }
    console.log('Connection Received from IP: ' + req.socket.remoteAddress + ' with id ' + id);

    //append websocket client to list of clients
    clients[id].push(ws);

    ws.on('message', function incoming(message) {
        if ('' === message) {
            //skip if message is blank
            return;
        }

        try {
            //process message as JSON object as "{"message": "string", "token": "string"}"
            message = JSON.parse(message);
        } catch(e) {
            return;
        }

        if (!message.hasOwnProperty('token') || '' === message.token) {
            //token was not sent or is empty
            return;
        }
        let token = message.token;
        console.log('Message received for token ' + token);

        if ('undefined' !== typeof clients[token] && clients[token]) {
            clients[token].forEach(function(client) {
                if (client !== ws && client.readyState === WebSocket.OPEN) {
                    //do not send message back to the sending client
                    client.send(message.message + ' ' + token);
                }
            });
        }

        //inform sending client message was sent
        ws.send('Sent: ' + message.message);
    });

    ws.on('close', function() {
        clients[id].forEach(function(client, index) {
            if (client === ws) {
                //remove the client from the pool
                clients[id].splice(index, 1);
            }
        });
    });
});

html code

<button type="button" id="sendBtn" class="btn-primary">Send</button>

<script type="text/javascript">
    const socket = new WebSocket('ws://localhost:8080/{{ token }}');
    socket.onmessage = function(evt) {
        window.console.log(evt.data);
    };

    jQuery(function($) {
        $('#sendBtn').on('click', function() {
            const message = {
                "message": "Hello World",
                "token": "{{ token }}"
            };
            socket.send(JSON.stringify(message));
        });
    });
</script>
Will B.
  • 17,883
  • 4
  • 67
  • 69
  • Sorry, I could check your answer only today. I am not sure if your answer is working or not. I am getting `TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object. Received an instance of Object ` – S S Jun 22 '21 at 11:41
  • It is probably related to something with the data being sent from the client.. I copy/pasted the code I was using to test with. Would need to know which line the error was on to validate. – Will B. Jun 22 '21 at 12:51
  • Anyways thank you for your assist. It was difficult time learning websocket(node) for first time – S S Jun 22 '21 at 13:45