programing

webSocketServer node.js 클라이언트를 차별화하는 방법

projobs 2021. 1. 18. 07:31
반응형

webSocketServer node.js 클라이언트를 차별화하는 방법


node.js와 함께 소켓을 사용하려고하는데 성공했지만 내 코드에서 클라이언트를 구별하는 방법을 모르겠습니다. 소켓과 관련된 부분은 다음과 같습니다.

var WebSocketServer = require('ws').Server, 
    wss = new WebSocketServer({port: 8080});
wss.on('connection', function(ws) {
    ws.on('message', function(message) {
        console.log('received: %s', message); 
        ws.send(message);
    });
    ws.send('something');
});

이 코드는 내 클라이언트 js에서 잘 작동합니다.

그러나 특정 사용자 또는 내 서버에서 소켓이 열려있는 모든 사용자에게 메시지를 보내고 싶습니다.

제 경우에는 클라이언트로 메시지를 보내고 응답을 받았지만 다른 사용자는 아무것도 표시하지 않습니다.

예를 들어 user1이 webSocket을 통해 서버에 메시지를 보내고 소켓이 열려있는 user2에게 알림을 보내고 싶습니다.


배열 CLIENTS []에 사용자 ID를 할당 할 수 있습니다. 여기에는 모든 사용자가 포함됩니다. 아래와 같이 모든 사용자에게 직접 메시지를 보낼 수 있습니다.

var WebSocketServer = require('ws').Server,
    wss = new WebSocketServer({port: 8080}),
    CLIENTS=[];

wss.on('connection', function(ws) {
    CLIENTS.push(ws);
    ws.on('message', function(message) {
        console.log('received: %s', message);
        sendAll(message);
    });
    ws.send("NEW USER JOINED");
});

function sendAll (message) {
    for (var i=0; i<CLIENTS.length; i++) {
        CLIENTS[i].send("Message: " + message);
    }
}

nodejs에서 ws 클라이언트를 직접 수정하고 각 클라이언트에 대해 개별적으로 사용자 정의 속성을 추가 할 수 있습니다. 또한 전역 변수 wss.clients 가 있으며 어디서나 사용할 수 있습니다. 다음 코드를 시도하고 두 개의 클라이언트에서 연결을 시도하십시오.

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({
    server: httpsServer
});


wss.getUniqueID = function () {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
    }
    return s4() + s4() + '-' + s4();
};

wss.on('connection', function connection(ws, req) {
    ws.id = wss.getUniqueID();

    wss.clients.forEach(function each(client) {
        console.log('Client.ID: ' + client.id);
    });
});

클라이언트 연결 URL에서 직접 매개 변수를 전달할 수도 있습니다.

https://myhost:8080?myCustomParam=1111&myCustomID=2222

연결 함수에서 이러한 매개 변수를 가져오고 이러한 매개 변수를 ws 클라이언트에 직접 할당 할 수 있습니다.

wss.on('connection', function connection(ws, req) {

    const parameters = url.parse(req.url, true);

    ws.uid = wss.getUniqueID();
    ws.chatRoom = {uid: parameters.query.myCustomID};
    ws.hereMyCustomParameter = parameters.query.myCustomParam;
}

Worlize 서버 의이 코드 조각 은 정말 많은 도움이되었습니다. ws를 사용하더라도 코드는 쉽게 적응할 수 있어야합니다. 여기서 중요한 부분을 선택했습니다.

// initialization
var connections = {};
var connectionIDCounter = 0;

// when handling a new connection
connection.id = connectionIDCounter ++;
connections[connection.id] = connection;
// in your case you would rewrite these 2 lines as
ws.id = connectionIDCounter ++;
connections[ws.id] = ws;

// when a connection is closed
delete connections[connection.id];
// in your case you would rewrite this line as
delete connections[ws.id];

이제 연결된 코드에 표시된대로 broadcast () 및 sendToConnectionId () 함수를 쉽게 만들 수 있습니다.

도움이되기를 바랍니다.


It depends which websocket you are using. For example, the fastest one, found here: https://github.com/websockets/ws is able to do a broadcast via this method:

var WebSocketServer = require('ws').Server,
   wss = new WebSocketServer({host:'xxxx',port:xxxx}),
   users = [];
wss.broadcast = function broadcast(data) {
wss.clients.forEach(function each(client) {
  client.send(data);
 });
};

Then later in your code you can use wss.broadcast(message) to send to all. For sending a PM to an individual user I do the following:

(1) In my message that I send to the server I include a username (2) Then, in onMessage I save the websocket in the array with that username, then retrieve it by username later:

wss.on('connection', function(ws) {

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

      users[message.userName] = ws;

(3) To send to a particular user you can then do users[userName].send(message);


you can use request header 'sec-websocket-key'

wss.on('connection', (ws, req) => {
  ws.id = req.headers['sec-websocket-key']; 

  //statements...
});

You can check the connection object. It has built-in identification for every connected client; you can find it here:

let id=ws._ultron.id;
console.log(id);

I'm using fd from the ws object. It should be unique per client.

var clientID = ws._socket._handle.fd;

I get a different number when I open a new browser tab.

The first ws had 11, the next had 12.


One possible solution here could be appending the deviceId in front of the user id, so we get to separate multiple users with same user id but on different devices.

ws://xxxxxxx:9000/userID/<<deviceId>>


By clients if you mean the open connections, then you can use ws.upgradeReq.headers['sec-websocket-key'] as the identifier. And keep all socket objects in an array.

But if you want to identify your user then you'll need to add user specific data to socket object.


If someone here is maybe using koa-websocket library, server instance of WebSocket is attached to ctx along side the request. That makes it really easy to manipulate the wss.clients Set (set of sessions in ws). For example pass parameters through URL and add it to Websocket instance something like this:

const wss = ctx.app.ws.server
const { userId } = ctx.request.query

try{

   ctx.websocket.uid = userId

}catch(err){
    console.log(err)
}

ReferenceURL : https://stackoverflow.com/questions/13364243/websocketserver-node-js-how-to-differentiate-clients

반응형