node.js child_process #surwn绕过stdin / stdout内部缓冲区

时间:2017-01-23 13:11:14

标签: node.js buffer spawn

我正在使用child_process#spawn通过node.js使用外部二进制文件。每个二进制文件根据语言搜索字符串中的精确单词,并根据输入文本生成输出。他们没有内部缓冲区。用法示例:

  • echo "I'm a random input" | ./my-english-binary 生成The word X is in the sentence
  • 等文字
  • cat /dev/urandom | ./my-english-binary产生无限的ouptut

我想将这些二进制文件中的每一个用作“服务器”。我希望在满足以前找不到的语言之后启动新的二进制实例,必要时使用stdin.write()向其发送数据,并使用stdout.on('data')事件直接获取其输出。问题是在将大量数据发送到stdin.write()之前未调用stdout.on('data')。 stdout或stdin(或两者)可能有内部阻塞缓冲区...但我想尽快输出,否则,程序可能会在新输入出现之前等待数小时并解锁stdin.write()或stdout.on('数据')。如何更改内部缓冲区大小?或者我可以使用其他非阻塞系统吗?

我的代码是:

const spawn = require('child_process').spawn;
const path = require('path');

class Driver {

  constructor() {
    // I have one binary per language
    this.instances = {
      frFR: {
        instance: null,
        path: path.join(__dirname, './my-french-binary')
      },
      enGB: {
        instance: null,
        path: path.join(__dirname, './my-english-binary')
      }
    }
  };

  // this function just check if an instance is running for a language
  isRunning(lang) {
    if (this.instances[lang] === undefined)
      throw new Error("Language not supported by TreeTagger: " + lang);
    return this.instances[lang].instance !== null;
  }

  // launch a binary according to a language and attach the function 'onData' to the stdout.on('data') event
  run(lang, onData) {
    const instance = spawn(this.instances[lang].path,{cwd:__dirname});
    instance.stdout.on('data', buf => onData(buf.toString()));
    // if a binary instance is killed, it will be relaunched later
    instance.on('close', () => this.instances[lang].instance = null );
    this.instances[lang].instance = instance;
  }

  /**
   * indefinitely write to instance.stdin()
   * I want to avoid this behavior by just writing one time to stdin
   * But if I write only one time, stdout.on('data') is never called
   * Everything works if I use stdin.end() but I don't want to use it
   */
  write(lang, text) {
    const id = setInterval(() => {
      console.log('setInterval');
      this.instances[lang].instance.stdin.write(text + '\n');
    }, 1000);
  }

};

// simple usage example
const driver = new Driver;
const txt = "This is a random input.";

if (driver.isRunning('enGB') === true)
  driver.write('enGB', txt);
else {
  /** 
   * the arrow function is called once every N stdin.write()
   * While I want it to be called after each write
   */
  driver.run('enGB', data => console.log('Data received!', data));
  driver.write('enGB', txt);
}

我试图:

  • 在stdin.write()周围使用cork()和uncork()。
  • 将child_process.stdout()传递给自定义Readable和Socket。
  • 在stdin,stdout和上述可读
  • 中将highWaterMark值覆盖为1和0
  • 我忘记了很多其他的事情......

此外,我不能使用stdin.end(),因为每次新文本到达时我都不想杀死我的二进制文件实例。有没有人有想法?

0 个答案:

没有答案