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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:18:30