简体   繁体   English

奇怪的node.js和redis行为

[英]weird node.js and redis behaviour

I've got a problem that defies explanation. 我有一个无法解释的问题。 Here's what i want: 这就是我想要的:

  • Client connects to node server through socket.io, sends his SID 客户端通过socket.io连接到节点服务器,发送其SID
  • Redis verifies if said SID is in its store, if not, don't emit 'authenticated', if the sid is in the store, then emit 'authenticated' Redis验证所述SID是否在其商店中,如果不是,则不发出“已认证”,如果sid在商店中,则发出“已认证”
  • Upon receiving the authentication, the extra options are given 收到身份验证后,将提供其他选项

Sounds pretty straightforward, and it should be. 听起来很简单,应该如此。 However this happens: 然而,这发生了:

  • Client connects with a SID thats in the redis store 客户端使用Redis存储中的SID连接
  • Node.js server verifies that the SID is in the store but fails to emit said 'authenticated' Node.js服务器验证SID在存储中,但无法发出“已验证”

However, when i restart the node server, everything seems to work just fine :S. 但是,当我重新启动节点服务器时,一切似乎都可以正常工作:S。 But when i proceed to remove the key from the store, and add it again (by ?auth and ?logout) the 'authenticated' is again not emitted. 但是,当我继续从商店中删除密钥,并再次添加它(通过?auth和?logout)时,“ authenticated”不会再次发出。

Client code: 客户代码:

<?php
session_start();
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1

require "./libraries/Predis.php";


if(isset($_GET['logout'])) {
    session_regenerate_id();
}

$sid =  sha1(session_id());
$redis = new Predis\Client();

echo "<h1>SID: " . $sid . "</h1>";

if(isset($_GET['auth'])) {
    $redis->set($sid, mt_rand(1,20000));
    $redis->expire($sid, 1800);
    echo "auth set<br />";
}

if ($redis->get($sid)) {  
    // he is authenticad, show something else
    echo "auth found<br />";
}

?>
<html>
<head>
    <title>Node Test VTclient</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
    <script src="http://the_server.dev:11337/socket.io/socket.io.js"></script>
</head>
<body>
    <p id="text">access denied</p>
    <script type="text/javascript">
        var connected = false;
        var authenticated = false;
        if(typeof io == 'undefined') {
            trigger_error();        
        } else {

            var socket = io.connect('http://vtvserver.dev:11337/', {
                 'reconnection delay' : 1,
                 'max reconnection attempts' : 1
            });

            socket.on('connect', function (data) {

                connected = true;             
                socket.emit('success_connect',{sid: '<?php echo $sid; ?>'});
                $('#text').html('connected');

                socket.on('get_bids', function (data) {              
                    $('#bids').html('');
                    if(typeof data === 'object') {
                        $.each(data.rows, function(key, value) {
                            add_bid(value.bid_id, value.bid_amount);
                        });
                    }                      
                }).on('reconnecting', function (reason) {

                    trigger_error(reason);
                    $('#text').html('disconnected');
                    socket.disconnect();

                }).on('authenticated', function(data) {
                    $('#text').html('authorised!'); 
                    // successful auth
                    $('#bidding').show();

                }).on('disconnect', function (data) {

                    connected = false;

                }).on('bid_placed', function (data) {

                    add_bid(data.id, data.amount);

                }).on('own_bid_placed', function(data){

                    if(!data.error) {
                        alert('bieding geplaatst!');
                    } else {
                        alert('Uw bieding is ongeldig.');
                    }
                });
        });


        }

        function trigger_error(reason) {
            $('#text').html('Server is down...');
        }

        function add_bid(id, amount) {
            $('#bids').append($('<option>', { value : id }).text(amount)); 
        }

    $(function() {
        $('#disconnect').click(function() {
            if(connected === true) {
                socket.disconnect();
                $('#text').html('Disconnected from server.');
            }
        });

        $('#bid').click(function() {
            var amount = $('#amount').val();

            // commit the bid to the server
            socket.emit('add_bid', {amount: amount});
        });
    })
    </script>
     <label for="bids">Biedingen:</label> 
     <select name="bids" id="bids" multiple='multiple' style='width:100px; height:150px'></select>
     <fieldset style="display:none" id="bidding">
       <legend>Plaats bieding</legend>
        <label for="amount"><Bedrag: </label><input type="text" id="amount" name="amount" value='0' />
        <button id="bid">Bied</button>
    </fieldset> 

    <button id="disconnect">Disconnect</button>
</body>

Server code: 服务器代码:

var
    cfg = require("./config").cfg(),              
    sys = require("sys"),
    url = require("url"),
    http = require("http"),
    qs = require("querystring"),
    redis  = require("redis"),
    redis_client  = redis.createClient(cfg.redis.port, cfg.redis.host),
    express  = require("express"),
    mysql = require("./node_modules/mysql"),
    //ch   = require("./node_modules/channel").channel(cfg.msg_backlog, cfg.msg_truncate),
    sio = require('./node_modules/socket.io');


//require ('./node_modules/sherpa');
//require ('./node_modules/log'); 
require ('./node_modules/simplejsonp');

redis_client.on("error", function (err) {
        console.log("REDIS error: " + err);
});

var app = express();

app.configure(function(){

});

app.get('/',
        function (req,res) {
            if (req.headers['referer']) {
                log(req.connection.remoteAddress + " / " + req.headers['referer']);
            }
            else {
                log(req.connection.remoteAddress + " /");
            }
            res.writeHead(307, {'Location':'http://' + cfg.domain});
            res.end();
});

app.listen(cfg.server_port, cfg.server_public_ip);

/* Create the IO server */
var server = http.createServer(app);
var io = sio.listen(server);

// minify the browser socket io client
io.enable('browser client minification');

server.listen(11337);

io.set('log level', 2);

io.sockets.on('disconnect', function(data) {
    console.log('client disconnected');
});



/**
 * Enable authentication
 * @param  {[type]}   handshakeData [description]
 * @param  {Function} callback      [description]
 * @return {[type]}                 [description]
 */

// Anonymous or authenticaed user?
io.on('connection', function (socket) {

    var sql_client = mysql.createClient({
      host      : cfg.database.server,
      user      : cfg.database.user,
      password  : cfg.database.pass,
      database  : cfg.database.primary
    });

    console.log('incoming connection');    
    socket.emit('access', 'granted');

    socket.on('success_connect', function(data) {        
        console.log('Client connected: ' + data.sid);

        sql_client.query('SELECT * FROM `bids`',function(error, results) {
              if(error) {
                  console.log('Error: ' + error);
                  return false;
              }
              console.log('emitting get_bids...');
              socket.emit('get_bids', {rows: results});
        });

        // if the user is authenticated, flag it as such
        redis_client.get(data.sid, function(err, reply) {

          var authenticated = false;

          if(err) {
            console.log("Fatal error: " + err);
          }

          console.log('Got response from redis...');
          if(reply !== null) {
            console.log('auth succesful for '+data.sid);
            socket.emit('authenticated', { sid : data.sid}); 
            authenticated = true;
          }

          // LEFT JOIN user_bids ON user_bids_bid_id = bid_id

          if(authenticated === true) {
          // safest way: only listen for certain commands when the user is autenticated
          socket.on('add_bid', function(data) {
              var amount = data.amount;           
              var values = [amount];
              var error = false;

              // validate the amount
              var regexp = new RegExp(/^\d{1,5}(\.\d{1,2})?$/);

              if(typeof amount === 'undefined' || amount < 1.00 || !amount.match(regexp)) {
                 error = 'invalid_bid';
              }

              socket.emit('own_bid_placed', {amount: amount, error : error});

              if(!error) {

                sql_client.query('INSERT INTO `bids` SET bid_amount = ?',values,function(error, results) {
                     if(error) {
                        console.log('Error: ' + error);
                     }
                     console.log('Inserted: ' + results.affectedRows + ' row.');
                     console.log('Id inserted: ' + results.insertId);

                     io.sockets.emit('bid_placed', {id: results.insertId, amount: amount});
                  }); 
              }
            });
          }
        });
    });

    sql_client.end();

    socket.on('disconnect', function(data) {
        console.log('Client disconnected');
    });
});

console.log('Server running at http://'+cfg.server_public_ip+':'+cfg.server_port+'/');

I fixed it by creating the redis client when a client connects: 我通过在客户端连接时创建redis客户端来解决此问题:

io.on('connection', function (socket) {
var redis_client  = redis.createClient(cfg.redis.port, cfg.redis.host);
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM