PHP TCP Socket无法读取PLC 502端口数据求助
PHP TCP Socket无法读取PLC Modbus TCP(502端口)数据的问题排查与修复
问题代码中的核心错误
- 角色混淆:PLC在502端口提供Modbus TCP服务,你的PHP程序应作为客户端发起连接,但代码错误使用了
socket_bind()(服务端绑定端口的操作),而非socket_connect()。 - 函数误用:
socket_recvfrom()是UDP通信的函数,TCP场景下应使用socket_read()或socket_recv()。 - 缺少协议请求:Modbus TCP是请求-响应模式,必须先发送符合规范的请求报文,PLC才会返回数据,直接等待接收无意义。
修正后的代码示例(以读取保持寄存器为例)
<?php $plcAddress = "10.22.100.210"; $plcPort = 502; // 创建TCP socket $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("无法创建Socket: " . socket_strerror(socket_last_error()) . "\n"); // 连接PLC $result = socket_connect($socket, $plcAddress, $plcPort) or die("无法连接PLC: " . socket_strerror(socket_last_error()) . "\n"); // 构造Modbus TCP请求报文(示例:读取起始地址0的1个保持寄存器) // 格式:事务处理标识(2字节)+协议标识(2字节)+长度(2字节)+单元标识(1字节)+功能码(1字节)+起始地址(2字节)+寄存器数量(2字节) $request = pack('nnnCnn', 0x0001, 0x0000, 0x0006, 0x01, 0x03, 0x0000, 0x0001); // 发送请求 socket_write($socket, $request, strlen($request)) or die("发送请求失败: " . socket_strerror(socket_last_error()) . "\n"); // 读取响应(Modbus响应最小长度是9字节) $response = socket_read($socket, 1024) or die("读取响应失败: " . socket_strerror(socket_last_error()) . "\n"); // 解析响应(转换为十六进制便于查看) echo "PLC响应数据(十六进制): " . bin2hex($response) . "\n"; // 关闭socket socket_close($socket); ?>
额外注意事项
- 确保PHP的
sockets扩展已启用(可通过phpinfo()查看)。 - 检查PHP运行环境的防火墙是否允许访问PLC的502端口。
- 不同PLC的Modbus参数(如单元标识、寄存器地址)可能不同,需根据PLC手册调整请求报文。
内容的提问来源于stack exchange,提问作者tamer aktı
相关产品推荐
相关产品推荐

