2016-06-09 1 views
0

Tout d'abord - Je suis au courant de ce answer à un genre de problème similaire.Communication client TCP NodeJS

Problème

J'ai un protocole tiers, qui utilise TCP \ IP. Ce protocole définit que le serveur répond à chaque message reçu. Côté client (que j'essaie de mettre en œuvre), je dois attendre la réponse du serveur.

Le problème se produit lorsque j'essaie d'envoyer des messages. J'ai besoin d'attendre la réponse du premier message avant d'envoyer le second (comme le ping-pong).

J'ai essayé de faire plusieurs écritures sur mon NodeJS tcp client comme celui-ci, qui ne compréhensible en raison de async:

client.connect(connectOptions, function() { 
    client.write(message1); 
    client.write(message2); 
}); 

Comme je l'ai déjà dit, j'ai un composant tiers, dont les réponses aux deux messages avec une valeur numérique. Alors, quand

client.on('data',function (data) {}); 

déclenche un événement, je ne peux pas distinguer quel message, était responsable de la réponse. Contrairement au answer lié, je n'ai pas la possibilité de marquer la réponse du côté serveur. Je suis nouveau sur node.js, alors j'essaie de trouver la meilleure façon de résoudre ce genre de problème, car il est de nature: faire des choses synchrones dans l'environnement asynchrone.

Répondre

0

Une façon serait d'utiliser une liste commune des gestionnaires pour assurer le suivi des demandes et réponses:

var handlers = []; 
client.connect(connectOptions, function() { 
    client.write(message1); 
    handlers.push(function msg1_handler(data) {}); 

    client.writewrite(message2); 
    handlers.push(function msg2_handler(data) {}); 
}); 
client.on('data',function(data) { 
    var handler = handlers.shift(); 
    handler(data); 
}); 

Tout cela devrait évidemment être enveloppé dans une catégorie distincte contenant à la fois un handlersclient objets. C'est juste un exemple de comment le faire. L'inconvénient est que si le serveur ne répond pas à une demande, alors vous avez un désordre complet, difficile de faire les choses correctement.


Une autre idée est de tampon demandes:

function BufferedClient(cli) { 
    this.cli = cli; 
    this.buffer = []; 
    this.waiting_for_response = false; 
    var that = this; 
    cli.on('data', function(data) { 
     that.waiting_for_response = false; 
     var pair = that.buffer.shift(); 
     var handler = pair[0]; 
     process.nextTick(function() { 
      // we use .nextTick to avoid potential 
      // exception in handler which would break 
      // BufferedClient 
      handler(data); 
     }); 
     that.flush(); 
    }); 
}; 
BufferedClient.prototype = { 
    request: function(msg, handler) { 
     this.buffer.push([handler, msg]); 
     this.flush(); 
    }, 
    flush: function() { 
     var pair = this.buffer[0]; 
     if (pair && !this.waiting_for_response) { 
      this.cli.write(pair[1]); 
      this.waiting_for_response = true; 
     } 
    } 
}; 

Cette fois que vous envoyez des demandes de manière séquentielle (donc comme synchrone) en raison de la façon dont .request() et .on('data') travail de gestionnaire avec .flush() fonction. Utilisation:

client.connect(connectOptions, function() { 
    var buff_cli = new BufferedClient(client); 
    buff_cli.request(message1, function(data) { }); 
    buff_cli.request(message2, function(data) { }); 
}); 

Maintenant, même si le serveur ne répond pas vous n'avez pas de désordre. Cependant, si vous lancez parallèlement buff_cli.request et que l'un d'entre eux échoue, vous aurez une fuite de mémoire (puisque this.buffer devient plus grand alors que rien ne le vide parce que BufferedClient attend une réponse). Cela peut être résolu en ajoutant des délais d'attente sur le socket.

Notez que les deux solutions supposent que le serveur ne pousse jamais rien au client sans une demande.

Si j'étais vous j'irais avec la deuxième solution. Notez que je n'ai pas testé le code de sorte qu'il pourrait être buggé mais l'idée générale devrait être ok.Lorsque vous implémentez un serveur (et je sais que vous ne le faites pas dans ce cas), vous devez toujours avoir un protocole qui correspond à chaque requête avec une réponse d'une manière unique. Une façon serait d'envoyer un identifiant unique avec chaque requête pour que le serveur reçoive le même identifiant. Dans un tel scénario, la demande de réponse avec la réponse est très facile et vous évitez tout ce gâchis.

+0

Thx. Je pense, je voudrais aller avec la deuxième approche, je dois l'essayer en premier, mais pour ce que je vois, il pourrait résoudre mon problème. –