13 Linux 广播和组播


前言 (含目录)


广播

范围: 仅局域网

/**
 * @name server.c
 * @author IYATT-yx
 * @brief UDP广播 - 服务器端
 */
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(11111);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(fd, (struct sockaddr *)&server, sizeof(server)))
    {
        perror("bind error");
        exit(EXIT_FAILURE);
    }

    // 初始化客户端地址信息
    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_port = htons(11112);
    // 使用广播地址给客户端发数据
    inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr);
    // 打开广播权限
    int flag = 1;
    setsockopt(AF_INET, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));

    while (true)
    {
        // 发送广播
        static int counter = 0;
        char buf[1024] = {0};
        sprintf(buf, "%d 广播中...", ++counter);
        if (sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&client, sizeof(client)) == -1)
        {
            perror("sendto error");
            exit(EXIT_FAILURE);
        }
        printf("已广播内容: %s\n", buf);
        sleep(1);
    }
    close (fd);
}
/**
 * @name client.c
 * @author IYATT-yx
 * @brief UDP广播 - 客户端
 */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

int main(void)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    // 绑定IP和端口
    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_port = htons(11112);
    if (inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr) == -1)
    {
        perror("inet_pton error");
        exit(EXIT_FAILURE);
    }
    if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1)
    {
        perror("bind error");
        exit(EXIT_FAILURE);
    }

    while (true)
    {
        char buf[1024] = {0};
        if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) == -1)
        {
            perror("recvfrom error");
            exit(EXIT_FAILURE);
        }
        printf("收到广播内容: %s\n", buf);
    }
    close(fd);

}

在这里插入图片描述




组播 (多播)

范围: 局域网和Internet

组播地址
224.0.0.0 ~ 224.0.0.255预留的组播地址 (永久组地址), 地址224.0.0.0保留不做分配, 其它地址供路由协议使用
224.0.1.0 ~ 224.0.1.255公用组播地址, 可以用于Internet; 需申请.
224.0.2.0 ~ 238.255.255.255用户可用的组播地址 (临时组地址), 全网范围内有效
239.0.0.0 ~ 239.255.255.255本地管理组播地址, 仅在特定的本地范围内有效
struct ip_mreqn
{
	// 多播组的IP地址
	struct in_addr imr_multiaddr;
	// 本地某一网络设备接口的IP地址
	struct in_addr imr_interface;
	// 网卡编号
	int imr_ifindex;
};

struct in_addr
{
	in_addr_t s_addr;
};
/**
 * @name server.c
 * @author IYATT-yx
 * @brief UDP组播 - 服务器端
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <ifaddrs.h>

int main(void)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(11111);
    server.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(fd, (struct sockaddr *)&server, sizeof(server)))
    {
        perror("bind error");
        exit(EXIT_FAILURE);
    }

    // 初始化客户端地址信息
    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_port = htons(11112);
    // 使用组播地址给客户端发数据
    inet_pton(AF_INET, "239.0.0.100", &client.sin_addr.s_addr);
    // 打开组播权限
    struct ip_mreqn flag;
    inet_pton(AF_INET, "239.0.0.100", &flag.imr_multiaddr.s_addr);
    inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr);

    // 获取网卡名,然后用网卡名获取接口号
    struct ifaddrs *ifAddrStruct = NULL;
    getifaddrs(&ifAddrStruct);
    char name[10];
    while (ifAddrStruct != NULL)
    {
        if (strcmp(ifAddrStruct->ifa_name, "lo") != 0)
        {
            strcpy(name, ifAddrStruct->ifa_name);
            break;
        }
        ifAddrStruct = ifAddrStruct->ifa_next;
    }
    char chIdx[3];
    sprintf(chIdx, "%d", if_nametoindex(name));
    int intIdx = atoi(chIdx);
    flag.imr_ifindex = intIdx;
    setsockopt(AF_INET, IPPROTO_IP, IP_MULTICAST_IF, &flag, sizeof(flag));

    while (true)
    {
        // 发送
        static int counter = 0;
        char buf[1024] = {0};
        sprintf(buf, "%d 运行中...", ++counter);
        if (sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&client, sizeof(client)) == -1)
        {
            perror("sendto error");
            exit(EXIT_FAILURE);
        }
        printf("已发送内容: %s\n", buf);
        sleep(1);
    }
    close (fd);
}
/**
 * @name client.c
 * @author IYATT-yx
 * @brief UDP组播 - 客户端
 */
#define _GNU_SOURCE
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <ifaddrs.h>

int main(void)
{
    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    if (fd == -1)
    {
        perror("socket error");
        exit(EXIT_FAILURE);
    }

    // 绑定IP和端口
    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_port = htons(11112);
    if (inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr) == -1)
    {
        perror("inet_pton error");
        exit(EXIT_FAILURE);
    }
    if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1)
    {
        perror("bind error");
        exit(EXIT_FAILURE);
    }

    struct ip_mreqn flag;
    inet_pton(AF_INET, "239.0.0.100", &flag.imr_multiaddr.s_addr);
    inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr);

    // 获取网卡名,然后用网卡名获取接口号
    struct ifaddrs *ifAddrStruct = NULL;
    getifaddrs(&ifAddrStruct);
    char name[10];
    while (ifAddrStruct != NULL)
    {
        if (strcmp(ifAddrStruct->ifa_name, "lo") != 0)
        {
            strcpy(name, ifAddrStruct->ifa_name);
            break;
        }
        ifAddrStruct = ifAddrStruct->ifa_next;
    }
    char chIdx[3];
    sprintf(chIdx, "%d", if_nametoindex(name));
    int intIdx = atoi(chIdx);
    flag.imr_ifindex = intIdx;
    setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &flag, sizeof(flag));

    while (true)
    {
        char buf[1024] = {0};
        if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) == -1)
        {
            perror("recvfrom error");
            exit(EXIT_FAILURE);
        }
        printf("收到组播内容: %s\n", buf);
    }
    close(fd);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值