2017-09-13 2 views
-1

Un collègue et moi devons interfacer son programme C et mon script Node.js. J'essaie de prouver le concept de l'utilisation de stdio pour passer des messages entre les deux et jusqu'à présent, le concept n'est pas prouvé! Le script de noeud démarre l'exécutable en tant que processus enfant lors de l'initialisation, mais ne parvient pas à envoyer ou à recevoir des données.Comment envoyer à stdin et recevoir de stdout du programme C de Node.js?

J'ai écrit un programme C très simple qui renvoie à stdout tout ce qu'il reçoit sur stdin. Je ne suis pas un programmeur C alors je espère que je n'ai rien fait trop choquant dans 16 lignes: p:

stream_echo.c:

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

#define BUFFER_SIZE 255 

int main(void) { 

    char * buffer = calloc(BUFFER_SIZE, 1); 

    while(fgets(buffer, BUFFER_SIZE, stdin) != NULL) { 

     //Echo back on stdout: 
     fprintf(stdout, "echo: %s", buffer); 
    } 
} 

et les tests dans la console montre qu'il fonctionne comme prévu : stream_echo.c running in terminal window

Le script Node.js qui appelle cet exécutable est la suivante:

child_stdio.js

(function() { 
    "use strict"; 

    var jcp = require("child_process").spawn("./stream_echo", [], { 
      detached: false, 
      stdio: "pipe" 
     }), 

     counter = 0, 

     timer, 

     sendData = function() { 
      console.log("In sendData. Connected: " + jcp.connected); 

      counter += 1; 
      jcp.stdin.write("This is data " + counter + "\r\n"); 

      timer = setTimeout(sendData, 2000); 
     }; 


    //******** STDIN ******** 
    jcp.stdin.on("close", (data) => { 
     console.log("stdin closed."); 
     if (timer) { 
      clearTimeout(timer); 
     } 
    }); 


    //******** STDOUT ******** 
    jcp.stdout.on("data", (data) => { 
     console.log("stdout: " + data); 
    }); 

    jcp.stdout.on("close", (data) => { 
     console.log("stdout closed."); 
    }); 


    //******** STDERR ******** 
    jcp.stderr.on("data", (data) => { 
     console.log("stderr: " + data); 
    }); 

    jcp.stderr.on("close", (data) => { 
     console.log("stderr closed."); 
    }); 


    //******** PROCESS ******** 
    jcp.on("close", (code, signal) => { 
     console.log("Child process closed.\nCode: " + code + "\nSignal: " + signal); 
    }); 

    jcp.on("exit", (code, signal) => { 
     console.log("Child process exited.\nCode: " + code + "\nSignal: " + signal); 
    }); 

    jcp.on("disconnect",() => { 
     console.log("Child process disconnected."); 
    }); 

    console.log("jcp.pid: " + jcp.pid); 
    console.log("Connected: " + jcp.connected); 
    console.log("Calling sendData for the first time...."); 
    sendData(); 

}()); 

Quand je lance ce script, plusieurs tentatives d'envoyer des données au processus de l'enfant sont faits et pas les erreurs sont signalées (en dépit de la propriété connected du processus étant faux), mais ne reçoit aucun message de retour non plus. Lorsque je tue le processus enfant, les événements de fermeture de flux et les événements de fermeture de processus sont déclenchés et le script se termine avec élégance.

Execution of child_stdio.js

Je ne comprends pas pourquoi connected est faux, mais les événements proches déclenchent. Je pense que c'est un indice majeur.

Quelqu'un peut-il me dire ce que de nombreuses heures au chalut Internet ne peuvent pas?

Répondre

1

Lorsque stdout n'est pas connecté à un terminal, il est mis en mémoire tampon. Cela signifie que la sortie ne sera pas vidée jusqu'à ce que le tampon se remplisse ou que l'application se termine.

Ajoutez fflush(stdout) après fprintf dans votre application C.

+0

Merci beaucoup! Cela semble être les neuf dixièmes du problème. Je ne savais pas qu'il pouvait se comporter différemment sur le terminal et j'étais convaincu que le problème était dans mon script Node. Je regardais complètement au mauvais endroit. –