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

发布于 2022-09-12 00:33:57 字数 3478 浏览 15 评论 0

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

Snipaste_2020-01-07_13-20-46.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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦在夏天 2022-09-19 00:33:57

plc 的返回值会根据收到的值变化而变化吗?

plc 每次收到值一样吗?

建议先抓包看下是发送方向还是接收方向不对

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文