node.js套接字响应顺序和恢复套接字挂起

时间:2012-11-23 15:14:19

标签: node.js sockets sqlite sequence

通过socket连接查询带有node.js的sqlite3数据库时,我遇到以下两个问题:

  1. 使用node.js http客户端我请求一个node.js http服务器,结果的序列被混淆

  2. 我不时会收到一个套接字,它不可重现

  3. 这是服务器代码:

    var http = require('http');
    var url = require('url');
    var sqlite3 = require('sqlite3').verbose();
    var counter = 0;
    
    
    //create sqlite database for testing
    var db = new sqlite3.Database("db.sqlite3");
    db.serialize(function() {
      db.run("DROP TABLE IF EXISTS test");
      db.run("CREATE TABLE IF NOT EXISTS test (ID INTEGER)");
    
      var stmt = db.prepare("INSERT INTO test VALUES (?)");
      for (var i = 1; i <= 10; i++) {
          stmt.run(i);
      }
      stmt.finalize();
    });
    db.close();
    
    
    
    //run server
    http.createServer(function (req, res) {
    
        var queryData = url.parse(req.url, true).query;
        res.writeHead(200, {"Content-Type": "text/plain; charset=utf-8"});//, "connection": "keep-alive"
    
    
        var db = new sqlite3.Database(new Buffer(queryData.SQLServerAddress, "base64").toString('utf8'));
        db.serialize(function() {
            db.each(new Buffer(queryData.SQLStatement, "base64").toString('utf8'), function(err, row) {
                counter++;
                console.log(counter + " / " + JSON.stringify(row));
                res.end(JSON.stringify(row).toString());
            });
        });
        db.close();
        counter = 0;
    }).listen(1337, '127.0.0.1');
    
    console.log('Server running...');
    

    这是客户端代码:

    var http = require('http');
    
    for(i=1;i<=10;i++){
        var SQLServerAddress = new Buffer("db.sqlite3").toString('base64');
        var SQLStatement = new Buffer("SELECT * FROM test WHERE ID=" + i).toString('base64');
    
    
        var options = {
            host: "127.0.0.1",
            port: 1337,
            path: "/?SQLServerAddress=" + SQLServerAddress + "&SQLStatement=" + SQLStatement
        };
    
    
        callback = function(response){
            var str = "";
            response.on("data", function (chunk){
                str += chunk;
            });
    
            response.on("end", function (){
                console.log(str);
            });
        }
        http.request(options, callback).end();
    }
    

    我重复请求10次作为“压力测试”,有点......

    所以我在控制台收到的是例如。

    服务器端控制台:

    1 / {"ID":1}
    2 / {"ID":2}
    3 / {"ID":5}
    4 / {"ID":4}
    1 / {"ID":3}
    2 / {"ID":6}
    1 / {"ID":7}
    2 / {"ID":9}
    3 / {"ID":10}
    4 / undefined
    

    客户端控制台:

    {"ID":1}
    {"ID":2}
    {"ID":5}
    {"ID":4}
    {"ID":3}
    {"ID":6}
    {"ID":7}
    {"ID":9}
    {"ID":10}
    
    events.js:68
            throw arguments[1]; // Unhandled 'error' event
                           ^
    Error: socket hang up
        at createHangUpError (http.js:1263:15)
        at Socket.socketCloseListener (http.js:1314:23)
        at Socket.EventEmitter.emit (events.js:123:20)
        at Socket._destroy.destroyed (net.js:357:10)
        at process.startup.processNextTick.process._tickCallback (node.js:244:9)
    

    我的问题是:

    1. 如何以正确的顺序保存结果?
    2. 我该怎么做才能防止套接字挂断?
    3. 提前致谢!

1 个答案:

答案 0 :(得分:0)

Node.js是一个基于异步事件的环境。

因此,运行调用函数的for循环只会将这些函数添加到处理队列中,但不会等待它们完成。

因此,您的所有请求都是并行启动的,并且无法保证将首先结束/传输。如果您想保证订单,您必须同步传输请求。下面的代码是未经测试的,但你应该明白,只有当一个请求结束时,下一个请求才会启动(这不会放在for循环中)。

var count = 0;
callback = function(response){
    var str = "";
    response.on("data", function (chunk){
        str += chunk;
    });

    response.on("end", function (){
        if (count++ < 10){
          http.request(options, callback).end();
        }
        console.log(str);
    });
}
http.request(options, callback).end();

不幸的是我不确定什么是从套接字挂断错误中恢复的最佳方法,但你可以尝试使用try / catch包围http.request方法,如果前一个引发错误,只需启动一个新请求