如何实现Node.js与C语言子进程的实时通信?
Node.js与C语言子进程实时通信问题解决
问题背景
在Debian GNU/Linux服务器上构建JavaScript API,需调用C语言编写的子进程实现实时通信,但当前Node.js仅能在子进程关闭后读取其stdout输出,无法在子进程写入stdout/stderr时立即响应。
当前代码
testNodeJS.js
const { spawn } = require("child_process"); var child = spawn("./testC.x"); child.stderr.on('data', function (data) { console.log(`child stderr:\n${data}`); }) child.stdout.on('data', (data) => { console.log(`child stdout:\n${data}`); }); child.stdin.write( 'FOO\n'); child.stdin.write( 'bar\n');
testC.c
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( int argc, char * argv[] ) { char input_string[ 1023 + 1 ]; printf("Start: %s\n", argv[0]); while ( 1 ) { scanf("%s", &input_string); //reading stdin while(!getchar()); //cleaning stdin printf( "Read: >%s<\n", input_string); //write stdout if( strcmp( input_string, "end" ) == 0 ) //End testC.x { printf("End: %s", argv[0] ); return 0; } } }
现象
- 执行
testNodeJS.js时,控制台无任何输出,仅保持等待状态,无法实时获取子进程输出 - 若在JS代码中添加
child.stdin.write( 'end\n');,子进程关闭后会一次性输出所有内容
问题原因
C语言标准库的printf输出缓冲策略会根据输出目标变化:
- 当输出到终端时,采用行缓冲,换行时自动刷新缓冲区
- 当输出被Node.js的
spawn接管(非终端环境),会切换为全缓冲,只有缓冲区填满或进程退出时才会刷新输出,导致Node.js无法实时接收数据
解决方案
方案1:在C代码中手动刷新缓冲区
每次调用printf后,手动调用fflush(stdout)强制刷新输出缓冲区,同时修正原代码中scanf的参数错误(input_string本身是指针,无需加&):
修改后的testC.c:
#include <stdio.h> #include <string.h> #include <stdlib.h> int main( int argc, char * argv[] ) { char input_string[ 1023 + 1 ]; printf("Start: %s\n", argv[0]); fflush(stdout); // 强制刷新缓冲区 while ( 1 ) { scanf("%s", input_string); // 修正:去掉多余的& while(!getchar()); printf( "Read: >%s<\n", input_string); fflush(stdout); // 每次输出后刷新 if( strcmp( input_string, "end" ) == 0 ) { printf("End: %s\n", argv[0] ); // 补充换行符,确保输出完整 fflush(stdout); return 0; } } }
方案2:启动子进程时禁用缓冲
通过stdbuf命令启动C子进程,强制关闭stdout的缓冲:
修改testNodeJS.js中的spawn调用:
var child = spawn('stdbuf', ['-o', '0', './testC.x']);
-o 0表示将stdout的缓冲设置为0(无缓冲),这样C子进程的输出会直接发送给Node.js,无需修改C代码。
验证
修改后执行testNodeJS.js,控制台会实时输出:
child stdout: Start: ./testC.x child stdout: Read: >FOO< child stdout: Read: >bar<
子进程保持运行状态,等待后续输入。
内容的提问来源于stack exchange,提问作者Banone
相关产品推荐
相关产品推荐

