简体   繁体   中英

node.js socket response order and recover socket hang up

I have the following 2 problems when querying a sqlite3 database with node.js through a socket connection:

  1. with a node.js http client I request a node.js http server, the result's sequence is mixed up

  2. from time to time I get a socket hang up, it is not reproduceable

Here's the server code:

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...');

And here's the client code:

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

I repeat the request 10 times as a "stress test", kind of...

So what I receive in the console is eg

Server side console:

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

And client side console:

{"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)

My questions are:

  1. how do I keep the results in the right order?
  2. what can I do to prevent the socket hang up?

Thanks in advance!

Node.js is an asynchronous event based environment.

Therefore, running a for loop which calls a function simply adds these functions to the processing queue but doesn't wait for them to be finished.

All your requests are therefore started in parallel and there is no guarantee which will end/transmit first. If you want to guarantee order, you have to transmit requests synchronously. The below code is untested, but you should get the idea, only once the one request has ended the next one is started up (this is not placed in a for loop).

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

Unfortunately I'm not sure what's the best way to recover from a socket hangup error, but you can try to surround the http.request method with a try/catch and simply start a new request if a previous one caused an error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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