te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Websockets: send messages and notifications to all clients except sender - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Websockets: send messages and notifications to all clients except sender - Stack Overflow

programmeradmin3浏览0评论

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 would like to send notifications to other connected users that new user has joined to the chat. I am trying to give a unique ID to every connected user, but the first assigned ID is re-writed by every new user and I cannot diferentiate users.

Server:

// list of users
var CLIENTS=[];
var id;

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

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

id = Math.random();
CLIENTS[id] = ws;
CLIENTS.push(ws);

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

    if(received.type == "login"){
        ws.send(message);  // send message to itself

        /* *********************************************************** */
        /* *** Here I trying to check if message es from sender *** */

        sendNotes(JSON.stringify({
            user: received.name,
            type: "notes"
        }), ws, id);

        /* *********************************************************** */
    }else if(received.type == "message"){
        sendAll(message); // broadcast messages to everyone including sender
    }

});

ws.on('close', function() {
    console.log('user ' + CLIENTS[ws] + ' left chat');
    delete CLIENTS[ws];
});

});

function sendNotes(message, ws, id) {
    console.log('sendNotes : ', id);
    if (CLIENTS[id] !== ws) {
        console.log('IF : ', message);
        for (var i = 0; i < CLIENTS.length; i++) {
            CLIENTS[i].send(message);
        }
    }else{
        console.log('ELSE : ', message);
    }
}

   function sendAll(message) {
       for (var i=0; i < CLIENTS.length; i++) {
          CLIENTS[i].send(message); // broadcast messages to everyone including sender
       }
   }

Client:

loginButton.addEventListener("click", function(){
    name = usernameInput.value;

    if(name.length > 0){
        socket.send(JSON.stringify({
            type: "login",
            name: name
        }));
    }

});

function sendData() {
    var data = dataChannelSend.value;
    var userName = document.getElementById('greetingUser').innerHTML;

    socket.send(JSON.stringify({
        username : userName,  // fetch user name from browser, after login
        type : "message",
        message : data
    }));
}

socket.onmessage = function(message) {

    var envelope = JSON.parse(message.data);
    switch(envelope.type) {
        case "login":
            onLogin(envelope);
            break;
        case "message":
            showMessage(envelope);
            break;
    }
};

I would highly appreciate If you could give me any hint. Thanks

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 would like to send notifications to other connected users that new user has joined to the chat. I am trying to give a unique ID to every connected user, but the first assigned ID is re-writed by every new user and I cannot diferentiate users.

Server:

// list of users
var CLIENTS=[];
var id;

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

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

id = Math.random();
CLIENTS[id] = ws;
CLIENTS.push(ws);

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

    if(received.type == "login"){
        ws.send(message);  // send message to itself

        /* *********************************************************** */
        /* *** Here I trying to check if message es from sender *** */

        sendNotes(JSON.stringify({
            user: received.name,
            type: "notes"
        }), ws, id);

        /* *********************************************************** */
    }else if(received.type == "message"){
        sendAll(message); // broadcast messages to everyone including sender
    }

});

ws.on('close', function() {
    console.log('user ' + CLIENTS[ws] + ' left chat');
    delete CLIENTS[ws];
});

});

function sendNotes(message, ws, id) {
    console.log('sendNotes : ', id);
    if (CLIENTS[id] !== ws) {
        console.log('IF : ', message);
        for (var i = 0; i < CLIENTS.length; i++) {
            CLIENTS[i].send(message);
        }
    }else{
        console.log('ELSE : ', message);
    }
}

   function sendAll(message) {
       for (var i=0; i < CLIENTS.length; i++) {
          CLIENTS[i].send(message); // broadcast messages to everyone including sender
       }
   }

Client:

loginButton.addEventListener("click", function(){
    name = usernameInput.value;

    if(name.length > 0){
        socket.send(JSON.stringify({
            type: "login",
            name: name
        }));
    }

});

function sendData() {
    var data = dataChannelSend.value;
    var userName = document.getElementById('greetingUser').innerHTML;

    socket.send(JSON.stringify({
        username : userName,  // fetch user name from browser, after login
        type : "message",
        message : data
    }));
}

socket.onmessage = function(message) {

    var envelope = JSON.parse(message.data);
    switch(envelope.type) {
        case "login":
            onLogin(envelope);
            break;
        case "message":
            showMessage(envelope);
            break;
    }
};

I would highly appreciate If you could give me any hint. Thanks

Share Improve this question edited Feb 23, 2016 at 8:48 johannesMatevosyan asked Feb 21, 2016 at 11:48 johannesMatevosyanjohannesMatevosyan 2,2282 gold badges36 silver badges43 bronze badges 0
Add a ment  | 

3 Answers 3

Reset to default 13

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.

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.

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 ining(message) {

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

    });


});
发布评论

评论列表(0)

  1. 暂无评论