Node.js net.Socket无法连接且无错误输出问题求助
Node.js TCP客户端连接运动控制卡无响应排查
问题描述
编写了如下Node.js代码用于连接局域网内运动控制卡并发送回原点命令:
var net = require('net'); const checkSum = (msg) => { if (msg.length === 0) return 256; let hash = 0; for (let i = 0; i < msg.length; i++) { let char = msg.charCodeAt(i); hash += char; } hash &= 0xFF; hash = 0x100 - hash; return hash; } const sendAndGetReply = (msg, ip, port) => { const message = msg + checkSum(msg).toString(); var client = new net.Socket() var reply = ""; var rts = false; console.log(`trying to connect ${ip}:${port}`); client.connect(port, ip) .on('connect', function () { console.log('Connected'); client.write(message); }) .on('error', e => console.log(e)) .on('data', function (data) { reply = data client.destroy(); // kill client after server's response }) .on('close', function () { rts = true; }); while (!rts) { } return reply; } const home = (serial, ip, port) => { const message = `HOME,${serial},`; const homeReply = sendAndGetReply( message, ip, port ); console.log(homeReply); if (homeReply != 0) { return false; } return true; } home("004-301023", "192.168.13.43", 80);
运行时仅输出trying to connect 192.168.13.43:80,既不显示“Connected”也无错误信息。目标主机可正常ping通,同类功能的Python脚本可正常运行,Node.js版本为v19.1.0。
问题分析与修复
核心问题:同步死循环阻塞事件循环
Node.js是单线程事件驱动模型,while (!rts) {}这个空循环会永久阻塞事件循环,导致所有异步回调(connect、error、data等)根本无法执行。这就是为什么看不到连接成功或错误提示的原因。
修复方案:改用Promise处理异步流程
将sendAndGetReply重构为返回Promise,通过异步等待替代死循环,同时完善错误处理和数据解析:
const net = require('net'); const checkSum = (msg) => { if (msg.length === 0) return 256; let hash = 0; for (let i = 0; i < msg.length; i++) { hash += msg.charCodeAt(i); } hash &= 0xFF; hash = 0x100 - hash; // 注意:若Python脚本是输出两位十六进制字符串(补前导零),需改为以下格式 // return hash.toString(16).padStart(2, '0').toUpperCase(); return hash.toString(); } const sendAndGetReply = (msg, ip, port) => { return new Promise((resolve, reject) => { const message = msg + checkSum(msg); const client = new net.Socket(); console.log(`trying to connect ${ip}:${port}`); client.connect(port, ip) .on('connect', () => { console.log('Connected'); client.write(message); }) .on('error', (err) => { console.error('Connection error:', err); reject(err); client.destroy(); }) .on('data', (data) => { // 将Buffer转为字符串,根据实际编码调整(如utf8/ascii) const reply = data.toString('utf8').trim(); console.log('Received reply:', reply); resolve(reply); client.destroy(); }) .on('close', () => { console.log('Connection closed'); // 若未收到数据就关闭,需处理空响应情况 if (!client.receivedData) { reject(new Error('Connection closed without receiving data')); } }); }); } const home = async (serial, ip, port) => { const message = `HOME,${serial},`; try { const homeReply = await sendAndGetReply(message, ip, port); // 根据实际响应格式判断,比如响应是"0"字符串则返回true return homeReply === '0'; } catch (err) { console.error('Home command failed:', err); return false; } } // 调用异步函数 home("004-301023", "192.168.13.43", 80) .then(result => console.log('Home operation result:', result)) .catch(err => console.error('Unexpected error:', err));
关键修复点说明
- 移除死循环:用Promise封装异步流程,通过
async/await实现同步风格的异步等待,不阻塞事件循环 - 完善错误处理:
error事件直接reject错误,确保能捕获连接超时、拒绝等问题 - 数据解析:将收到的Buffer转为字符串,避免直接输出Buffer对象
- 校验和格式对齐:注释中提到的十六进制格式调整,需和Python脚本的校验和生成逻辑完全一致(比如Python是否输出两位十六进制)
- 异步函数调用:
home改为async函数,调用时用then/catch处理结果和异常
额外排查建议
- 检查Python脚本的校验和生成逻辑,确保Node.js的
checkSum函数输出完全一致(比如是否是十进制字符串、十六进制字符串,是否补零) - 用
telnet 192.168.13.43 80测试TCP连接是否正常,排除端口防火墙问题 - 开启Node.js的调试日志,或用Wireshark抓包对比Node.js和Python的TCP报文差异
内容的提问来源于stack exchange,提问作者John Andrew Kypriotakis
相关产品推荐
相关产品推荐

