program story

node-websocket-server : 단일 node.js 프로세스에 대해 여러 개의 개별 "방송"을 가질 수 있습니까?

inputbox 2020. 12. 25. 09:44
반응형

node-websocket-server : 단일 node.js 프로세스에 대해 여러 개의 개별 "방송"을 가질 수 있습니까?


동일한 node-websocket-server 앱 인스턴스 에서 실행되는 다른 websocket "연결"에서 브로드 캐스트 할 수 있는지 알고 싶습니다 . 단일 node.js 서버 프로세스에서 여러 방이있는 채팅방 서버가 각 방의 참가자에게만 메시지를 브로드 캐스팅한다고 상상해보십시오. 프로세스 당 하나의 채팅방 솔루션을 성공적으로 구현했지만 다음 단계로 넘어 가고 싶습니다.


Socket.IO 위에 구축 된 Push-it : http://github.com/aaronblohowiak/Push-It 을 사용해보고 싶을 것입니다 . 디자인은 Bayeux 프로토콜을 준수합니다.

그러나 redis pubsub를 사용하는 것이 필요하면 http://github.com/shripadk/Socket.IO-PubSub 를 확인할 수 있습니다.

구체적으로 질문에 대한 답변 : 웹 소켓 서버에 연결된 모든 클라이언트의 배열을 유지할 수 있습니다. 그리고 아마도 해당 클라이언트의 하위 집합에 브로드 캐스트할까요? 브로드 캐스트 방법은 본질적으로 내부적으로이를 수행합니다. node-websocket-server / Socket.IO는 연결된 모든 클라이언트의 배열을 유지하고 각 클라이언트에 메시지를 "전송"하는 모든 클라이언트를 순환합니다. 코드의 요점 :

// considering you storing all your clients in an array, should be doing this on connection:
clients.push(client)

// loop through that array to send to each client
Client.prototype.broadcast = function(msg, except) {
      for(var i in clients) {
          if(clients[i].sessionId !== except) {
             clients[i].send({message: msg});
          }
      }
}

따라서 특정 채널에만 메시지를 릴레이하려면 클라이언트가 구독하는 모든 채널 목록을 유지하십시오. 다음은 간단한 예입니다 (시작하기 위해).

clients.push(client);


Client.prototype.subscribe = function(channel) {
      this.channel = channel;
}

Client.prototype.unsubscribe = function(channel) {
     this.channel = null;
}

Client.prototype.publish = function(channel, msg) {
      for(var i in clients) {
         if(clients[i].channel === channel) {
            clients[i].send({message: msg});
         }
      }
}

더욱 쉽게 EventEmitters를 사용하십시오. 따라서 node-websocket-server / Socket.IO에서 메시지가 수신되는 위치를 확인하고 메시지를 구문 분석하여 유형 (subscribe / unsubscribe / publish)을 확인하고 유형에 따라 메시지와 함께 이벤트를 내 보냅니다. 예:

Client.prototype._onMessage = function(message) {
       switch(message.type) {
         case 'subscribe':
             this.emit('subscribe', message.channel);
         case 'unsubscribe':
             this.emit('unsubscribe', message.channel);
         case 'publish':
             this.emit('publish', message.channel, message.data);
         default:

       }
}

앱의 on ( 'connection')에서 발생하는 이벤트를 수신합니다.

client.on('subscribe', function(channel) {
     // do some checks here if u like
     client.subscribe(channel);
});
client.on('unsubscribe', function(channel) {
     client.unsubscribe(channel);
});
client.on('publish', function(channel, message) {
     client.publish(channel, message);
});

도움이 되었기를 바랍니다.


다른 답변이 만들어 졌을 때 방이 기능 인지 확실하지 않지만 문서에는 정확히 찾고있는 기능이 있습니다. 따라서 해당 링크로 이동하여 rooms.

다음은 사이트의 예입니다.

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.join('justin bieber fans');
  socket.broadcast.to('justin bieber fans').emit('new fan');
  io.sockets.in('rammstein fans').emit('new non-fan');
});

다른 답변을 기반으로 확장에 더 중점을 두었고 기본 제공 버전이 제안 된 답변과 함께 확장된다면 통찰력을 원할 것입니다.


Shripad K의 대답은 매우 잘 구성되어 있습니다. 잘 했어.

나는 그 솔루션에 몇 가지 확장 문제가있을 것이라고 생각합니다.

500 개의 채팅방에 10,000 명의 동시 사용자가있는 경우 모든 사용자가 메시지를 보낼 때마다 10,000 명의 클라이언트를 모두 반복해야합니다. 주어진 방에있는 클라이언트 목록을 redis의 구조에 저장하고이 목록을 가져 와서 해당 클라이언트에게 보내는 것이 더 빠를 것이라고 생각합니다.

1) 실제로 더 빠른지 확실하지 않습니다. 2) 고객을 참조 할 수있는 redis에 무엇이 저장 될 수 있는지 확실하지 않습니다. 서버에있는 모든 클라이언트의 해시가 고유 ID와 redis에있을 수 있으며 채팅방 당 사용자 ID 집합을 저장할 수 있습니까?

이것이 더 확장 가능한 것 같습니까?

저는 fzysqr을 기반으로 노드 채팅 서버를 작성했으며 널리 배포하기 전에 여러 채팅에 대해 확장 가능하도록 만들어야합니다.


방에서 내 간단한 테스트 채팅은

chat.js 같습니다.

var app = require('http').createServer(handler)
  , io = require('socket.io').listen(app)
  , fs = require('fs')

app.listen(80);

function handler (req, res) {
  fs.readFile(__dirname + '/chat.html',
  function (err, data) {
    if (err) {
      res.writeHead(500);
      return res.end('Error loading chat.html');
    }

    res.writeHead(200);
    res.end(data);
  });
}

io.sockets.on('connection', function (socket) {

    socket.on('join', function (room) {
        if (Array.isArray(room)) {
            var i;
            for (i = 0; i < room.length; ++i) {
                console.log('join room ' + room[i]);
                socket.join(room[i]);
            }
        } else if (typeof room === 'string') {
            console.log('join room ' + room);
            socket.join(room);
        }
    });

    socket.on('leave', function (room) {
        if (typeof room === 'string') {
            console.log('leave room ' + room);
            socket.leave(room);
        }
    });

    socket.on('post', function (data) {
        io.sockets.in(data.room).emit('publish', data);
    });

});


및 chat.html :

<html>
<head>
<title>Node js test</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<script src="http://127.0.0.1:80/socket.io/socket.io.js"></script>
</head>
<body>
<h2>Node js test</h2>

<div style="height:400px;">
    <div id="controls" style="height:400px; display: inline-block; width:20%; float:left; background-color:lightyellow;">
        <input id="room1_check" type="checkbox" value="room_1" checked /><label for="room1_check">Room 1</label><br/><br/>
        <input id="room2_check" type="checkbox" value="room_2" /><label for="room2_check">Room 2</label><br/><br/>
        <input id="room3_check" type="checkbox" value="room_3" checked /><label for="room3_check">Room 3</label><br/><br/>
        <input id="room4_check" type="checkbox" value="room_4" /><label for="room4_check">Room 4</label><br/><br/>
        <input id="room5_check" type="checkbox" value="room_5" /><label for="room5_check">Room 5</label><br/><br/>
    </div>

    <div id="stream" style="height:400px; display: inline-block; width:40%; background-color:white; overflow:auto;"></div>

    <div id="post" style="height:400px; display: inline-block; width:40%; float:right; background-color:yellow;">
        <label for="postRoom">Room: </label>
        <select id="postToRoom">
            <option value="room_1">Room 1</option>
            <option value="room_2">Room 2</option>
            <option value="room_3">Room 3</option>
            <option value="room_4">Room 4</option>
            <option value="room_5">Room 5</option>
        </select>
        <br/><br/>
        <label for="postBy">By: </label>
        <select id="postBy">
            <option value="User 1">User 1</option>
            <option value="User 2">User 2</option>
            <option value="User 3">User 3</option>
            <option value="User 4">User 4</option>
            <option value="User 5">User 5</option>
        </select>
        <br/><br/>
        <label for="postMessage">Message:</label><br/>
        <textarea id="postMessage" style="width:80%; height:100px;" ></textarea>
        <br/><br/>
        <input id="postBtn" type="button" value="post message" />
    </div>

</div>


<script>
    var socket = io.connect('http://127.0.0.1:80');

    var checkedRooms = [];
    $('#controls :checked').each(function() {
        checkedRooms.push($(this).val());
    });
    socket.emit('join', checkedRooms);

    socket.on('publish', function (post) {
        //console.log(data);
        $("#stream").html($("#stream").html() + "room: " + post.room + "<br/>");
        $("#stream").html($("#stream").html() + "by: " + post.by + "<br/>");
        $("#stream").html($("#stream").html() + "on: " + post.on + "<br/>");
        $("#stream").html($("#stream").html() + "message: " + unescape(post.message) + "<br/>");
        $("#stream").html($("#stream").html() + "=============================================<br/>");
    });

    $('#controls :checkbox').change(function () {
        socket.emit(this.checked ? 'join' : 'leave', $(this).val());
     });

    $("#postBtn").click(function() {
        socket.emit('post', {room: $("#postToRoom").val(), message: escape($("#postMessage").val()), by: $("#postBy").val(), on: (new Date() + "") });
    });

</script>

</body>
</html>

참조 URL : https://stackoverflow.com/questions/4445883/node-websocket-server-possible-to-have-multiple-separate-broadcasts-for-a-si

반응형