You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js与C#编写的.exe进程除stdout外的通信方式咨询

Node.js与C# .exe进程的替代通信方案指南

嘿,很高兴你在探索Node.js和外部.exe进程的通信方式!除了你已经在用的stdout/stdin/stderr标准流之外,确实还有不少更灵活的方案,尤其是当你需要更复杂的双向通信、更高性能或者更结构化的数据传输时。下面给你梳理几个主流的方向,附简单示例帮助你快速上手:

1. 命名管道(Named Pipes)

这是Windows平台下本地进程通信的经典方案,轻量且性能出色,Node.js和C#都原生支持。它通过系统内核实现进程间的数据传递,不需要经过网络栈。

Node.js 端(作为客户端连接管道)

const net = require('net');
// 管道路径格式为 \\\\.\\pipe\\[管道名]
const pipeClient = net.connect({ pipe: '\\\\.\\pipe\\MyAppPipe' }, () => {
  console.log('已连接到C#进程的命名管道');
  pipeClient.write(JSON.stringify({ type: 'greet', message: '来自Node.js的问候' }));
});

// 监听C#进程的响应
pipeClient.on('data', (data) => {
  const response = JSON.parse(data.toString());
  console.log(`收到C#的响应:${response.message}`);
  pipeClient.end();
});

C# 端(作为管道服务器)

using System.IO.Pipes;
using System.Text;
using System.Text.Json;

// 创建命名管道服务器
using var pipeServer = new NamedPipeServerStream("MyAppPipe");
Console.WriteLine("等待Node.js进程连接...");
pipeServer.WaitForConnection();

// 读取Node.js发送的数据
byte[] buffer = new byte[1024];
int bytesRead = pipeServer.Read(buffer, 0, buffer.Length);
string receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
var request = JsonSerializer.Deserialize<dynamic>(receivedData);
Console.WriteLine($"收到Node.js消息:{request.message}");

// 发送响应给Node.js
string response = JsonSerializer.Serialize(new { type = "response", message = "来自C#的回复" });
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
pipeServer.Write(responseBytes, 0, responseBytes.Length);

pipeServer.Close();

适用场景:Windows平台下的本地进程通信,需要低延迟、高可靠性的双向通信。


2. TCP套接字(TCP Sockets)

这是跨平台的通用方案,不管是Windows还是Linux都能使用。通过本地回环地址(127.0.0.1)实现进程间通信,本质是本地网络通信,兼容性极强。

Node.js 端(作为TCP服务器)

const net = require('net');
const tcpServer = net.createServer((socket) => {
  console.log('C#客户端已连接');
  
  socket.on('data', (data) => {
    const msg = data.toString().trim();
    console.log(`收到C#消息:${msg}`);
    socket.write("Node.js收到消息啦!");
  });
  
  socket.on('end', () => {
    console.log('C#客户端断开连接');
  });
});

tcpServer.listen(3000, '127.0.0.1', () => {
  console.log('TCP服务器监听在127.0.0.1:3000');
});

C# 端(作为TCP客户端)

using System.Net.Sockets;
using System.Text;

// 连接到Node.js的TCP服务器
using var tcpClient = new TcpClient();
tcpClient.Connect("127.0.0.1", 3000);
Console.WriteLine("已连接到Node.js的TCP服务器");

// 发送消息
string message = "Hello from C#!";
byte[] msgBytes = Encoding.UTF8.GetBytes(message);
NetworkStream stream = tcpClient.GetStream();
stream.Write(msgBytes, 0, msgBytes.Length);

// 接收响应
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
string response = Encoding.UTF8.GetString(buffer, 0, bytesRead);
Console.WriteLine(`收到Node.js响应:${response}`);

tcpClient.Close();

适用场景:跨平台的本地/远程进程通信,需要标准化、易于调试的通信方式。


3. UDP套接字(UDP Sockets)

如果你的通信场景不需要严格的可靠性(比如日志上报、状态通知),UDP是更轻量的选择,它不需要建立连接,延迟更低,但可能会丢包。

Node.js 端

const dgram = require('dgram');
const udpClient = dgram.createSocket('udp4');

const message = Buffer.from('来自Node.js的UDP消息');
// 发送到C#的UDP监听端口
udpClient.send(message, 0, message.length, 3001, '127.0.0.1', (err) => {
  if (err) throw err;
  console.log('UDP消息已发送');
});

// 监听C#的响应
udpClient.on('message', (msg, rinfo) => {
  console.log(`收到C#的UDP响应:${msg.toString()}`);
  udpClient.close();
});

C# 端

using System.Net;
using System.Net.Sockets;
using System.Text;

// 创建UDP客户端监听端口3001
using var udpClient = new UdpClient(3001);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);

Console.WriteLine("等待UDP消息...");
byte[] receivedBytes = udpClient.Receive(ref remoteEP);
string message = Encoding.UTF8.GetString(receivedBytes);
Console.WriteLine(`收到Node.js消息:${message}`);

// 发送响应
string response = "来自C#的UDP回复";
byte[] responseBytes = Encoding.UTF8.GetBytes(response);
udpClient.Send(responseBytes, responseBytes.Length, remoteEP);

udpClient.Close();

适用场景:对可靠性要求不高,但追求低延迟、高吞吐量的场景,比如实时状态推送。


4. 共享内存(Memory-Mapped Files)

如果需要传输大量数据(比如文件、二进制流),共享内存是性能最优的方案——它直接在进程间共享内存区域,不需要复制数据。不过实现复杂度稍高,需要处理同步问题。

C# 端(创建共享内存)

using System.IO.MemoryMappedFiles;
using System.Text;

// 创建一个名为"MySharedMemory"的共享内存区域,大小为1MB
using var mmf = MemoryMappedFile.CreateOrOpen("MySharedMemory", 1024 * 1024);
using var stream = mmf.CreateViewStream();
using var writer = new BinaryWriter(stream);

// 写入数据
writer.Write("来自C#的共享内存数据");
Console.WriteLine("数据已写入共享内存");

// 等待Node.js读取(这里可以用信号量或其他同步机制)
Console.ReadLine();

Node.js 端(读取共享内存)

// 需要借助第三方包,比如 `mmap-io`
const mmap = require('mmap-io');

// 打开共享内存区域
const fd = mmap.openSync('MySharedMemory', 'r');
const buffer = mmap.mapSync(1024 * 1024, mmap.PROT_READ, mmap.MAP_SHARED, fd);

// 读取数据(注意编码和长度)
const message = buffer.toString('utf8', 0, buffer.indexOf('\0'));
console.log(`从共享内存读取到:${message}`);

mmap.unmapSync(buffer);
mmap.closeSync(fd);

适用场景:大数据量传输,需要极致性能的场景。


选择建议

  • 如果是Windows平台本地通信,优先选命名管道,性能好且原生支持;
  • 如果需要跨平台,TCP套接字是最稳妥的选择,调试和维护都很方便;
  • 低延迟、非可靠场景选UDP套接字;
  • 大数据量传输选共享内存(需要额外处理同步逻辑)。

这些方案都比标准流更灵活,能支持更复杂的双向通信模式,你可以根据自己的实际需求先从命名管道或TCP入手尝试~

内容的提问来源于stack exchange,提问作者João Menighin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:40:35