SylixOS下UDP组播测试程序

SylixOS下UDP组播测试

测试效果截图如下:
在这里插入图片描述

在这里插入图片描述

udp组播发送测试程序。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: umc_send.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2024 年 06 月 05 日
**
** 描        述: udp multicast send test program
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
/*********************************************************************************************************
** 名称: getInaddr_s2v
** 功能: 将字符串网络地址转为数值型网络地址
** 输入: pAddrString     字符串网络地址
** 输出: 数值型网络地址
*********************************************************************************************************/
struct sockaddr_in  getInaddr_s2v (CHAR  *pAddrString)
{
    in_addr_t   in_addr;
    in_port_t   in_port;
    CHAR        in_string[32];
    CHAR       *pcPtr;
    struct sockaddr_in addr = {0, AF_INET, 0, {INADDR_ANY}};


    if (pAddrString == NULL) {
        return  (addr);
    }

    strncpy(in_string, pAddrString, sizeof(in_string) - 1);

    pcPtr = strchr(in_string, ':');
    if (pcPtr == NULL) {
        return  (addr);
    }
    *pcPtr = '\0';

    in_addr = inet_addr(in_string);
    if (IPADDR_NONE == in_addr) {
        return  (addr);
    }

    in_port = strtoul(pcPtr + 1, NULL, 10);
    if (in_port == 65535) {
        return  (addr);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = in_addr;
    addr.sin_port        = htons(in_port);

    return  (addr);
}
/*********************************************************************************************************
** 名称: main
** 功能: 入口函数
** 输入: argc   参数个数
**       argv   参数列表
** 输出: 错误号
*********************************************************************************************************/
int main (int argc, char *argv[])
{
    int                sock;
    int                iLoop = 0;
    struct ip_mreq     mreq;
    struct sockaddr_in selfaddr  = {0, AF_INET, 0, {INADDR_ANY}};
    struct sockaddr_in groupaddr = {0, AF_INET, 0, {INADDR_ANY}};


    if (argc == 1) {
        printf("umc_send groupaddr [selfaddr]\n");
        return  (0);
    }

    if (argc > 1) {
        groupaddr = getInaddr_s2v(argv[1]);
    }

    if (argc > 2) {
        selfaddr = getInaddr_s2v(argv[2]);
    }

    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        perror("Socket creation failed");
        return  (0);
    }

    if (argc > 2) {
        if (bind(sock, (struct sockaddr *)&selfaddr, sizeof(selfaddr)) < 0) {
            perror("bind failed");
            close(sock);
            return  (0);
        }
    }

    if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &iLoop,sizeof(iLoop)) < 0) {
        printf("setsockopt error!\n");
        close(sock);
        return  (0);
    }

    mreq.imr_multiaddr.s_addr = groupaddr.sin_addr.s_addr;
    mreq.imr_interface.s_addr = selfaddr.sin_addr.s_addr;
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_ADD_MEMBERSHIP failed");
        close(sock);
        return  (0);
    }

    while (1) {
        const char *message = "udp multicast send test!";

        if (sendto(sock, message, strlen(message), 0, (struct sockaddr *)&groupaddr, sizeof(groupaddr)) < 0) {
            perror("Sending data failed");
        } else {
            printf("udp send test ok\n");
        }
        sleep(1);
    }

    close(sock);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

udp组播接收测试程序。

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: umc_recv.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2024 年 06 月 05 日
**
** 描        述: udp multicast recv test program
*********************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#include <netdb.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
/*********************************************************************************************************
** 名称: getInaddr_s2v
** 功能: 将字符串网络地址转为数值型网络地址
** 输入: pAddrString     字符串网络地址
** 输出: 数值型网络地址
*********************************************************************************************************/
struct sockaddr_in  getInaddr_s2v (CHAR  *pAddrString)
{
    in_addr_t   in_addr;
    in_port_t   in_port;
    CHAR        in_string[32];
    CHAR       *pcPtr;
    struct sockaddr_in addr = {0, AF_INET, 0, {INADDR_ANY}};


    if (pAddrString == NULL) {
        return  (addr);
    }

    strncpy(in_string, pAddrString, sizeof(in_string) - 1);

    pcPtr = strchr(in_string, ':');
    if (pcPtr == NULL) {
        return  (addr);
    }
    *pcPtr = '\0';

    in_addr = inet_addr(in_string);
    if (IPADDR_NONE == in_addr) {
        return  (addr);
    }

    in_port = strtoul(pcPtr + 1, NULL, 10);
    if (in_port == 65535) {
        return  (addr);
    }

    memset(&addr, 0, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = in_addr;
    addr.sin_port        = htons(in_port);

    return  (addr);
}
/*********************************************************************************************************
** 名称: main
** 功能: 入口函数
** 输入: argc   参数个数
**       argv   参数列表
** 输出: 错误号
*********************************************************************************************************/
int main (int argc, char *argv[])
{
    int                sock;
    int                optval = 1;
    socklen_t          fromlen;
    struct ip_mreq     mreq;
    struct sockaddr_in selfaddr  = {0, AF_INET, 0, {INADDR_ANY}};
    struct sockaddr_in groupaddr = {0, AF_INET, 0, {INADDR_ANY}};
    struct sockaddr_in fromaddr  = {0, AF_INET, 0, {INADDR_ANY}};

    if (argc < 3) {
        printf("umc_recv groupaddr selfaddr\n");
        return  (0);
    }

    groupaddr = getInaddr_s2v(argv[1]);
    selfaddr  = getInaddr_s2v(argv[2]);
    selfaddr.sin_port = groupaddr.sin_port;

    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
        perror("Socket creation failed");
        return  (0);
    }

    if (bind(sock, (struct sockaddr *)&selfaddr, sizeof(selfaddr)) < 0) {
        perror("bind failed");
        close(sock);
        return  (0);
    }

    // 设置地址重用,可选,用于在同一台机器上的多个进程接收同一组播流。否则同一时刻只能有一路socket能收到组播。
    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
        perror("setsockopt SO_REUSEADDR failed");
        close(sock);
        return  (0);
    }

    // 加入组播组
    mreq.imr_multiaddr.s_addr = groupaddr.sin_addr.s_addr;
    mreq.imr_interface.s_addr = selfaddr.sin_addr.s_addr;
    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_ADD_MEMBERSHIP failed");
        close(sock);
        return  (0);
    }

    while (1) {
        ssize_t len;
        char    buf[2048];

        fromlen = sizeof(fromaddr);
        len = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&fromaddr, &fromlen);
        if (len < 0) {
            perror("recvfrom failed");
            break;
        }
        buf[len] = '\0';
        printf("recv %d byte from %s:%d : %s\n",
                (INT)len, inet_ntoa(fromaddr.sin_addr), ntohs(fromaddr.sin_port), buf);
    }

    // 离开组播组,通常在程序退出前执行
    if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        perror("setsockopt IP_DROP_MEMBERSHIP failed");
    }

    close(sock);

    return  (0);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

相关推荐

  1. <span style='color:red;'>UDP</span>单<span style='color:red;'>播</span>

    UDP

    2024-06-13 09:34:02      56 阅读
  2. <span style='color:red;'>UDP</span>多<span style='color:red;'>播</span>

    UDP

    2024-06-13 09:34:02      34 阅读
  3. 、广播

    2024-06-13 09:34:02       37 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-13 09:34:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-13 09:34:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-13 09:34:02       82 阅读
  4. Python语言-面向对象

    2024-06-13 09:34:02       91 阅读

热门阅读

  1. Prometheus 监控系统

    2024-06-13 09:34:02       21 阅读
  2. 未来汽车网络安全行业发展趋势分析

    2024-06-13 09:34:02       34 阅读
  3. 在.NET Core 中处理并发冲突方法

    2024-06-13 09:34:02       30 阅读
  4. Jtti:ubuntu文件系统根目录磁盘空间不足怎么办

    2024-06-13 09:34:02       28 阅读