使用Node.js net模块实现ASTM over TCP/IP时输出异常问题
异常原因排查与结果说明
核心触发点
- 这本质是终端渲染的视觉错位,不是传输数据本身出错:ASTM 1394协议的帧天生带一组ASCII传输控制字符,包括帧起始标记STX(0x02)、块结束标记ETB(0x17)、文本结束标记ETX(0x03)、帧尾必带的CR回车符(0x0D,仅回车不附带换行)。这些不可见字符被直接输出到终端时,CR会强制把光标拉回当前行的行首,后续输出的报文BCC校验位、帧头字符会直接覆盖掉之前已经打印的日志前缀(比如你代码里固定拼接的“the string ----”段),最终出现你观察到的行首字符替换、内容错位的问题。你看到的错位的“E1”,其实就是报文末尾的BCC校验字段的两个可见字符,因为光标回跳被移到了行首位置,覆盖了原有内容。
- 你当前的通信逻辑缺少TCP流拆包处理:Node.js内置net模块是基于TCP字节流的通信模型,单次
data事件回调拿到的Buffer,既可能是多个ASTM帧粘在一起的混合内容,也可能是单个帧的不完整片段。直接把单次拿到的Buffer转字符串就做ENQ判断、ACK应答,长期运行有概率出现真的解析错误。
和console.log输出特性的关联
- 这个现象确实和终端输出的原生行为强相关,但不属于console.log的实现bug:
- console.log的默认行为是在输出内容末尾自动追加换行符
\n,但不会主动过滤字符串里自带的CR控制符,也不会主动修正光标位置。 - 只要输出内容里包含CR,终端就会严格按照控制符规则移动光标,自然造成视觉错位。
- 做个简单验证就能确认:打印前把字符串里所有ASCII控制符(0x01-0x1F范围)替换为可见占位符(比如把
\r替换成<CR>),就能看到完全无错位的完整日志内容。
- console.log的默认行为是在输出内容末尾自动追加换行符
目标报文的获取可行性
- 完全可以正常拿到破折号后面的目标ASTM报文内容。终端显示的错位只是渲染层面的视觉问题,Node.js内存里存储的字符串变量本身是完整、未被篡改的,不存在数据丢失。
- 建议补两处逻辑优化,从根源上解决显示问题和潜在的解析错误:
- 日志打印前,先对转码后的字符串做清洗,剔除或替换所有传输控制字符,避免CR触发的光标错位。
- 补充ASTM协议的流拆包逻辑,严格按照“STX起始、ETB/ETX结束、BCC校验位、CR帧尾”的帧边界规则,把连续的字节流切分成独立完整的帧,再逐帧做ENQ判断、ACK应答、报文解析,避免粘包/拆包导致的逻辑错误。
内容的提问来源于stack exchange,提问作者user14573658
相关产品推荐
相关产品推荐

