Linux下NodeJS与C程序通信报错:打开Unix域套接字失败
Node.js与C程序Unix套接字通信问题排查与解决
问题场景
在Linux环境下尝试用Node.js搭建IPC服务端与C程序通信,但C程序和echo命令写入目标文件时均报错,尽管文件存在。
Node.js服务端代码
'use strict'; const net = require('net'); const pipename = '/tmp/pipe1'; const fs = require('fs'); let server = net.createServer(function(socket){ console.log('A new connection'); socket.on('data',function(data){ console.log(data.toString()); }); socket.on('end',function(){ console.log('Closed connection'); }); }); server.on('error',console.log); fs.unlink(pipename,function(){ server.listen(pipename); }) //Test unix-socket server: setInterval(function(){ var stream = net.connect(pipename); stream.on('error',console.log); stream.write('hello'); stream.end(); },2000);
错误现象
- C程序调用
open打开文件时出错:
const char* pipename = "/tmp/pipe1"; int hPipe = open(pipename, O_WRONLY); //Error: No such device or address
- 执行
echo 'Hello World!' > /tmp/pipe1时报错:
bash: /tmp/pipe1: No such device or address
ls -l /tmp能看到该文件,类型标识为s:
srwxr-xr-x 1 root root 0 Sep 16 03:20 pipe1
原因分析
你混淆了Linux下两种不同的IPC机制:
- Node.js代码创建的是Unix域套接字,文件类型标识为
s,它是基于套接字API的双向通信对象,不能用普通文件的open()/write()操作 - 你预期的是命名管道(FIFO),文件类型标识为
p,这类文件可以用普通文件IO接口操作
解决办法
提供两种针对性方案:
方案1:修改C程序,用Unix套接字API连接Node.js服务
Unix套接字需要用套接字专用API操作,示例C代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> int main() { const char* pipename = "/tmp/pipe1"; int sockfd; struct sockaddr_un addr; // 创建Unix套接字 sockfd = socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(EXIT_FAILURE); } // 配置套接字地址 memset(&addr, 0, sizeof(struct sockaddr_un)); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, pipename, sizeof(addr.sun_path) - 1); // 连接到Node.js服务端 if (connect(sockfd, (struct sockaddr*)&addr, sizeof(struct sockaddr_un)) == -1) { perror("connect"); close(sockfd); exit(EXIT_FAILURE); } // 发送数据 const char* msg = "Hello from C program"; ssize_t bytes_sent = write(sockfd, msg, strlen(msg)); if (bytes_sent == -1) { perror("write"); } else { printf("Sent %zd bytes: %s\n", bytes_sent, msg); } close(sockfd); return 0; }
方案2:修改Node.js代码,使用命名管道(FIFO)通信
如果要保留C程序的open()/write()逻辑,Node.js需要切换到FIFO模式:
- Node.js端代码:
'use strict'; const fs = require('fs'); const pipename = '/tmp/pipe1'; const FIFO_MODE = 0o666; // 创建命名管道,已存在则跳过 try { fs.mkfifoSync(pipename, FIFO_MODE); } catch (err) { if (err.code !== 'EEXIST') throw err; } // 监听FIFO的数据读取 fs.createReadStream(pipename) .on('data', (data) => { console.log('Received:', data.toString()); }) .on('error', (err) => { console.error('Read error:', err); }); // 测试写入FIFO setInterval(() => { fs.writeFile(pipename, 'Hello from Node.js', (err) => { if (err) console.error('Write error:', err); }); }, 2000);
- C程序无需修改核心逻辑,注意FIFO需要两端都打开才不会阻塞。
注意事项
- Unix套接字性能更高,适合双向、频繁的IPC场景
- 命名管道实现简单,适合单向或半双向的简单数据传递
- 确保文件路径权限正确,避免因权限不足导致的访问失败
内容的提问来源于stack exchange,提问作者Mehrdad Nazmdar
相关产品推荐
相关产品推荐

