我正在做一个程序跟 plc(具体是三菱 5u,若你不了解 plc,可以简单把它看做一个 tcp & udp 应答站) 通讯。
按照协议,我通过 udp 发送四个字节,plc 返回 14 个字节,如下:
5a00 0001 # 发送的数据
da00 0001 1400 c0a8 c826 c0a8 c826 # plc 应答的数据
随后我写了如下代码,交叉编译后运行在一台 arm 机上,
#include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> #include <stdio.h> #include <unistd.h>
int main() { int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { printf("socket() failed\n"); return 0; }
struct sockaddr_in peer;
peer.sin_family = AF_INET;
peer.sin_port = htons(5560); // plc udp 端口
peer.sin_addr.s_addr = inet_addr("192.168.30.156"); // plc 目标地址
uint8_t realData[4] = {0x5a, 0x00, 0x00, 0x01};
int num = sendto(sock, realData, 4, 0, (struct sockaddr *)&peer, sizeof(peer));
if (num <= 0)
{
printf("sendto failed, num=%d, errno=%d\n", num, errno);
close(sock);
return 0;
}
printf("send to plc, num = %d, data = ", num);
for (int i = 0; i < 4; i = i + 2)
printf("%02x%02x ", realData[i], realData[i + 1]);
printf("\n");
socklen_t len = 0;
uint8_t recv_buf[1024] = {0};
ssize_t recv_len = recvfrom(sock, recv_buf, sizeof(recv_buf) - 1, 0, (struct sockaddr *)&peer, &len);
if (recv_len <= 0)
{
printf("recvfrom failed, recv_len=%d, errno=%d\n", recv_len, errno);
close(sock);
return 0;
}
printf("recv from plc, len = %d, data = ", recv_len);
for (int i = 0; i < recv_len; i = i + 2)
printf("%02x%02x ", recv_buf[i], recv_buf[i+1]);
printf("\n");
close(sock);
return 0;
}
执行结果如下:
$ ./5u
send to plc, num = 4, data = 5a00 0001
recv from plc, len = 14, data = da00 0001 1400 c0a8 468d c0a8 c826
468d 这两个字节是错的。反复执行,plc 返回的数据依然是这样。
随后在 windows 端利用 udp 调试工具,返回的结果是正确的:
程序其实很简单,协议也很简单,为什么就是错了呢?
随后我把上面的代码在虚拟机 ubuntu 14.04 编译执行了下,结果如下:
> hapoa@hapoa-virtual-machine:~$ ./5ul
send to plc, num = 4, data = 5a00 0001
recv from plc, len = 14, data = da00 0001 1400 c0a8 c858 c0a8 c826
只错了一个字节:58
很奇怪,难道和系统有关,随后又把上面的代码拷贝到虚拟机 ubuntu 18.04 上,编译执行如下:
ethson@ethson-virtual-machine:~$ ./5u
send to plc, num = 4, data = 5a00 0001
recv from plc, len = 14, data = da00 0001 1400 c0a8 c826 c0a8 c826
完全正确!
怎么会和系统有关呢?有点不理解。
难道 udp 在不同(版本)的系统之间有所区别么?希望有人能指教一下,或者可以提供别的思路,谢谢。
下面是我上面验证的三个系统内核版本(分别是 arm、ubuntu 14.04、ubuntu 18.04):
# cat /proc/version
Linux version 3.10.65 (gcc version 5.3.1 20160412 (Linaro GCC 5.3-2016.05) ) #391 SMP PREEMPT Tue Dec 24 10:08:42 CST 2019
hapoa@hapoa-virtual-machine:~$ cat /proc/version
Linux version 3.13.0-24-generic (buildd@batsu) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014
ethson@ethson-virtual-machine:~$ cat /proc/version
Linux version 4.15.0-66-generic (buildd@lgw01-amd64-044) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #75-Ubuntu SMP Tue Oct 1 05:24:09 UTC 2019
plc 的返回值会根据收到的值变化而变化吗?
plc 每次收到值一样吗?
建议先抓包看下是发送方向还是接收方向不对。 抓包只想确认一点。造成结果的是因为 1. 发送方发出的报文导致 plc每次收到的不同 最后返回不同。 还是 2. 发送方发出的报文相同 plc 收到的相同,并且返回的也相同。 如果是1 那就往发送方TX方向排查 如果是2 那就往发送方RX方向排查
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。