2012-11-23 104 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語句,只是開始,如果前一個新的請求一個導致了一個錯誤。