【问题标题】:How to design when using Node.js for a gaming pairing使用 Node.js 进行游戏配对时如何设计
【发布时间】:2012-07-05 04:01:56
【问题描述】:

我使用node.js进行游戏配对(例如,多个客户端连接服务器。如果有多个玩家,则它们相互连接;否则将被踢30秒)。

目前,我正在使用套接字进行连接(这可以检测到意外丢失的连接)。但我想不出一种优雅的配对方式:

var net = require('net');
var _clients = new Array();

net.createServer(function(_socket) {
  _socket.on('data', function(_data) {
    //Parse client data
    _clients.push(_socket);
    setTimeout(function(){
      _socket.write('kicked\n');
    },30*1000);
  _socket.on('close', function(data) {
    //Delete _socket from _clients
  }
}).listen(6969, '127.0.0.1');

setInterval(function(){
  var pair = new Array();
  while(_clients.length>2)
  {
    var _s1 = _clients.pop(), _s2 = _clients.pop();
    // Pair _s1 & _s2
  }
},2*1000);

当前的代码可以工作,但设计得非常糟糕:(

(1)使用SetInterval,而不是异步调用。 (2)维护像_clients这样的数组很不方便,因为我必须处理“踢”/丢失连接/对或其他情况。

PS。目前我正在按时间顺序配对客户端,但可能需要随机配对或其他条件以避免在线玩家不多时总是配对相同的人。

【问题讨论】:

    标签: sockets node.js


    【解决方案1】:

    为什么不使用类似下面的东西?

    无连接池

    var net = require('net')
    , pendingPair = null;
    
    net.createServer(function(_socket) {
      _socket.on('data', function(_data) {
        //Parse client data
        if(!pendingPair) {
          pendingPair = _socket;
        } else {
          //  Now you have a pair!
          var p1 = pendingPair
            , p2 = _socket;
    
          pendingPair = null;
        }
    }).listen(6969, '127.0.0.1');
    

    一旦建立连接,您就会获得自动配对。您仍然需要在某处跟踪这些套接字以启动客户端和断开连接,但您应该能够摆脱 setIntervals。

    带连接池

    var net = require('net')
      , _ = require('underscore')._
      , clients = {}
      , games = {};
    
    function setKickTimer(socket) {
        socket.kickTimer = setTimeout(function() {
            socket.write('kicked\n');
        }, 30 * 1000);
    }
    
    net.createServer(function(socket) {
        socket.id = Math.floor(Math.random() * 1000);
        setKickTimer(socket);
        clients[socket.id] = socket;
    
        socket.on('data', function(data) {
            socket.data = parseData(data);
        }
    
        socket.on('close', function(data) {
            var opponent = _.find(clients, function(client) { return client.opponentId === socket.id; });
            //  The opponent is no longer part of a pair.
            if(opponent) {
                delete opponent.opponentId;
                setKickTimer(opponent);
            }
    
            delete clients[socket.id];
        }
    
    }).listen(6969, '127.0.0.1');
    
    setInterval(function(){
        //  Get the client ids of clients who are not matched, and randomize the order
        var unmatchedClientIds = _.shuffle(_.keys(_.filter(clients, function(client) { return !client.opponentId; })));
        while(unmatchedClientIds > 2) {
            var c1 = unmatchedClientIds.pop(),
              , c2 = unmatchedClientIds.pop();
    
            clearTimeout(clients[c1].kickTimer);
            clearTimeout(clients[c2].kickTimer);
            clients[c1].opponentId = c2;
            clients[c2].opponentId = c1;
        }
    },2*1000);
    

    这不是一个完整的工作解决方案,但它应该让您了解如何管理断开的连接和将用户踢出队列。请注意,我使用underscore.js 来简化对集合的操作。

    【讨论】:

    • 非常感谢。这确实有助于删除间隔,但如果我想保留一个连接池并有条件地配对它们(只是不配对最近的两个),它就不起作用
    • 你可以做一个或另一个。如果你想要一个连接池和比连接顺序更随机的对,你可能不得不对间隔做一些事情。这不一定有什么问题。
    猜你喜欢
    • 1970-01-01
    • 2012-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多