Node-Red Buffer.from的VB等效实现及TCP通信无响应问题咨询
TCP双接口板卡VB通信迁移问题排查方案
问题概述
- 采购的TCP通信双接口板卡需接收指定字节数组才会返回目标响应
- Node-RED环境下通过function节点构造载荷、经TCP节点发送可正常收到板卡响应
- 通信逻辑迁移到自主开发的VB桌面应用时,始终无法收到设备响应
- 需要捕获Node-RED实际发送的原始字节,与VB构造的字节数组做比对排查差异
现有实现参考
Node-RED侧正常工作的载荷构造代码
Msg.payload = Buffer.from([8,121,50,3,100]);
测试验证:不使用
Buffer.from封装原始字节数组直接发送时,设备不会返回任何响应
当前VB侧测试代码
Imports System.Net Public Class Form1 Dim TCPClientz As Sockets.TcpClient Dim TCPClientStream As Sockets.NetworkStream Private Sub SendBytesButton_Click(sender As Object, e As EventArgs) Handles SendBytesButton.Click Dim sendbytes() As Byte = System.Text.Encoding.UTF8.GetBytes(bytestextbox.Text) TCPClientz = New Sockets.TcpClient(ServerTextBox.Text, PortTextBox.Text) 'IP端口配置验证正常,改端口会触发报错 TCPClientStream = TCPClientz.GetStream() TCPClientStream.Write(sendbytes, 0, sendbytes.Length) If TCPClientStream.DataAvailable = True Then '运行到此处始终检测不到可用数据 Dim rcvbytes(TCPClientz.ReceiveBufferSize) As Byte TCPClientStream.Read(rcvbytes, 0, CInt(TCPClientz.ReceiveBufferSize)) replytextbox.Text = System.Text.Encoding.UTF8.GetString(rcvbytes) End If End Sub End Class
问题根因与修复方案
1. 载荷构造逻辑错误
Node-RED中Buffer.from([8,121,50,3,100])是直接构造长度为5的原始字节数组,对应十六进制值为0x08 0x79 0x32 0x03 0x64。
当前VB代码通过UTF8编码文本框输入内容生成字节数组,本质是把输入的数字、逗号等字符转成对应编码的字节,和板卡要求的原始字节完全不匹配,设备识别不到合法指令自然不会响应。
修复方式:直接在VB中定义和Node-RED完全一致的原始字节数组,不要走字符串编码转换逻辑:
' 直接构造与Node-RED完全一致的5字节原始指令 Dim sendbytes() As Byte = New Byte() {8, 121, 50, 3, 100}
2. TCP接收逻辑存在缺陷
DataAvailable属性仅判断调用瞬间套接字缓冲区是否有数据,TCP传输存在网络延迟、设备响应延迟,发送完数据立刻调用该属性大概率返回False,直接跳过接收逻辑,永远拿不到响应。
修复方式:设置合理读取超时,循环读取缓冲区数据,不要依赖DataAvailable作为接收判断条件:
' 配置接收超时,单位毫秒,可根据设备实际响应速度调整 TCPClientz.ReceiveTimeout = 3000 TCPClientStream.Write(sendbytes, 0, sendbytes.Length) ' 初始化接收存储 Dim rcvBuffer As New List(Of Byte)() Dim readBuf(1023) As Byte Try While True Dim readLen As Integer = TCPClientStream.Read(readBuf, 0, readBuf.Length) If readLen = 0 Then Exit While ' 连接主动断开时退出循环 ' 追加读到的字节到总缓冲区 For i As Integer = 0 To readLen - 1 rcvBuffer.Add(readBuf(i)) Next ' 若设备协议有固定帧尾/固定长度规则,可在此处加判断,读完一帧即可提前退出循环 End While Catch ex As Sockets.SocketException ' 超时后如果已读到数据则正常处理,无数据再抛出异常 If rcvBuffer.Count = 0 Then Throw End Try ' 按设备实际返回的编码格式转字符串,不要默认使用UTF8 Dim fullRcvBytes() As Byte = rcvBuffer.ToArray() replytextbox.Text = System.Text.Encoding.ASCII.GetString(fullRcvBytes)
Node-RED原始发送字节捕获方法
不需要额外抓包工具,直接在Node-RED流内即可获取最准确的原始发送字节:
- 在TCP发送节点的输入端接入一个debug调试节点,调试节点配置为输出
完整msg对象,部署后触发一次发送 - 调试面板输出的
payload.buffer数组,就是实际送入TCP发送栈的原始字节,每个元素对应单字节的十进制值,可直接和VB构造的数组逐位比对 - 如果需要更直观的十六进制视图,可在构造载荷的function节点内加一行日志打印代码:
// 加在Msg.payload构造完成后 node.log("发送字节(HEX): " + Msg.payload.toString('hex'));
部署后在Node-RED系统日志面板即可看到发送字节的十六进制字符串,当前正确载荷的输出为0879320364,和VB字节数组转十六进制的结果对比即可确认构造逻辑是否一致。
内容的提问来源于stack exchange,提问作者BBestvin
相关产品推荐
相关产品推荐

