2012-11-23 166 views
4

我已经通过套接字连接与node.js的查询sqlite3的数据库时以下2个问题:的node.js插座响应顺序和恢复插座挂断

  1. 用的node.js http客户端请求我使Node.js的http服务器,结果的顺序混了

  2. 不时我得到一个插座挂断,它不是reproduceable

这里的服务器代码:

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. 我该怎么做才能防止套接字挂断?

在此先感谢!

+0

+1在问题中提供了大量有用的信息 –

回答

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(); 

不幸的是我不知道什么是从一个插座挂起错误中恢复的最佳方式,但你可以尝试以环绕http.request方法用try/catch语句,只是开始,如果前一个新的请求一个导致了一个错误。