Websockets:向除发件人之外的所有客户端发送消息和通知

时间:2016-02-21 11:48:40

标签: javascript json node.js websocket webrtc

我正在开发基于websockets和webrtc的聊天。我想向除发件人之外的所有连接用户发送邮件,但我找不到合适的解决方案。更具体地说,我想向新用户加入聊天的其他连接用户发送通知。 我试图为每个连接的用户提供一个唯一的ID,但是第一个分配的ID由每个新用户重新编写,我不能区分用户。

服务器:

// 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 comes 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
       }
   }

客户端:

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;
    }
};

如果你能给我任何暗示,我将非常感激。感谢

3 个答案:

答案 0 :(得分:1)

好的,我们现在以一种允许我们唯一标识正在连接的每个客户端的方式存储CLIENTS,并存储有关它们的任意信息以供以后检索。

下面的代码会向所有客户发送“notes”消息,然后将新连接的客户端添加到“所有客户”列表中。

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(供您参考):

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 CLIENT.HTML与它一起去:

<!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>

我用NWJS v0.12.3在客户端上运行服务器和Firefox测试了这个。

答案 1 :(得分:1)

这是一种发送给除发件人以外的所有已连接人的非常简单的方法。

在您的webSocketServer实例上创建一个广播功能,该功能将 接受两个参数。

repositories {
        google()
        mavenCentral()
        maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
        jcenter()
    }

就这样,广播方法将发送到每个连接的客户端 除了正在发送的那个人。

答案 2 :(得分:0)

这应该有效

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);
        });

    });


});