开发者社区> 问答> 正文

不同的 linux 系统版本 udp 返回的数据不同

我正在做一个程序跟 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 调试工具,返回的结果是正确的:

image.png

程序其实很简单,协议也很简单,为什么就是错了呢?

随后我把上面的代码在虚拟机 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

展开
收起
问问小秘 2020-01-09 18:04:32 1466 0
1 条回答
写回答
取消 提交回答
  • plc 的返回值会根据收到的值变化而变化吗?

    plc 每次收到值一样吗?

    建议先抓包看下是发送方向还是接收方向不对。 抓包只想确认一点。造成结果的是因为 1. 发送方发出的报文导致 plc每次收到的不同 最后返回不同。 还是 2. 发送方发出的报文相同 plc 收到的相同,并且返回的也相同。 如果是1 那就往发送方TX方向排查 如果是2 那就往发送方RX方向排查

    2020-01-09 18:09:49
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Alibaba Cloud Linux 3 发布 立即下载
ECS系统指南之Linux系统诊断 立即下载
ECS运维指南 之 Linux系统诊断 立即下载