libmodbus:两台工业树莓派间TCP点对点连接失败问题求助
作为ARM固件开发背景转Linux嵌入式,你已经搞定了单台localhost TCP测试和跨机RTU通信,这已经迈出了关键一步!现在跨机TCP连接超时的问题,咱们从基础链路到代码配置一步步排查:
1. 优先确认eth1链路的连通性(最可能的坑点)
你提到两台树莓派的eth1通过支持端口镜像的交换机互连,但这里有个容易忽略的关键:端口镜像功能本身是用来抓包的,它不会让两个端口直接进行双向通信。如果交换机上只把两个eth1端口配置成镜像源和镜像目的,那这两个端口之间是无法正常收发数据的。
验证方法:
- 在客户端树莓派执行:
ping 192.168.0.3 - 在服务器端树莓派执行:
ping 192.168.0.4
如果ping不通,说明链路本身有问题,你需要把这两个端口配置成交换机的普通交换端口(而非镜像端口),让它们处于同一个广播域内。
2. 检查服务器端的端口监听状态
确认服务器真的在eth1的IP(192.168.0.3)上监听502端口:
- 在服务器端执行:
ss -tulpn | grep 502- 如果输出中显示
LISTEN状态,且绑定地址是192.168.0.3:502或者0.0.0.0:502(监听所有接口),说明监听正常; - 如果绑定的是
127.0.0.1:502或者eth0的IP,那客户端从eth1发起的连接肯定无法到达。
- 如果输出中显示
代码层面检查:
你的服务器代码中modbus_new_tcp(TEST_ADDRESS, MODBUS_TCP_DEFAULT_PORT),请确认TEST_ADDRESS的值是"192.168.0.3"或者"0.0.0.0"(推荐后者,兼容多接口)。如果TEST_ADDRESS是localhost或者eth0的IP,就会导致eth1接口无法接收连接请求。
3. 排查Linux防火墙/iptables规则
树莓派默认可能开启了ufw防火墙,或者有iptables规则阻挡了502端口的入站连接:
- 临时关闭防火墙测试:
sudo ufw disable,然后重新尝试客户端连接; - 如果关闭后能连接,说明需要开放502端口:
sudo ufw allow 502/tcp; - 也可以直接检查iptables规则:
sudo iptables -L -n | grep 502,确认是否有允许TCP 502端口的入站规则。
4. 确认路由表是否正确引导流量走eth1
两台树莓派的eth1处于192.168.0.0/24网段,但系统可能默认把192.168.0.x的流量走eth0(因为eth0是DHCP获取的,可能有默认路由)。
验证方法:
在客户端执行:ip route get 192.168.0.3
- 如果输出显示
dev eth0,说明流量走了eth0而非eth1,这就会导致连接超时; - 需要添加静态路由让192.168.0.0/24网段的流量走eth1:
要让路由永久生效,可以编辑sudo ip route add 192.168.0.0/24 dev eth1/etc/dhcpcd.conf或者/etc/network/interfaces(根据树莓派的系统版本调整)。
5. 用Wireshark抓包验证流量
既然你的交换机支持端口镜像,现在可以用它来抓包确认:
- 把Wireshark连接到镜像端口,抓取eth1的流量;
- 启动客户端连接请求,看是否有TCP SYN包从192.168.0.4:xxx发送到192.168.0.3:502;
- 如果没有SYN包,说明客户端的流量根本没发出去(路由/接口问题);如果有SYN包但没有ACK回复,说明服务器端没收到(防火墙/监听问题)。
代码小提示:
你的服务器代码中,在modbus_tcp_listen之后调用了modbus_tcp_accept,这个逻辑是对的,但要确保modbus_tcp_listen成功绑定了正确的接口。如果绑定失败,代码会直接退出,你可以在modbus_tcp_listen的错误输出中更明确地打印绑定地址,方便排查。
内容的提问来源于stack exchange,提问作者Kristin Hansen

