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

问题描述 投票:0回答:1

我正在使用

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
    产生无限的输出

我想使用这些二进制文件作为“服务器”。我想在遇到以前从未找到的语言后启动一个新的二进制实例,必要时使用 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 和上述 Readable 中的 highWaterMark 值覆盖为 1 和 0
  • 还有很多其他的事情我忘记了...

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

node.js buffer spawn
1个回答
0
投票

对于 7 年后回顾这个话题的人来说,

cat /dev/urandom ...
将始终提供无限的输出。如果你想要特定的位数,你需要使用类似的东西
head -c 256 /dev/urandom > bytefilename.bytes
dd if=/dev/urandom count=1 bs=256 | sha256sum
(我最近在加密项目中使用后一个示例作为熵示例)

© www.soinside.com 2019 - 2024. All rights reserved.