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
*********************************************************************************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ScilogyHunter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值