如何在Linux 启用组播

news2024/11/16 21:42:20

第一章: 前言

多播技术,也被称为“组播”,是一种网络通信机制,它允许一个节点(发送者)向一组特定的节点(接收者)发送信息。这种方式在网络编程中非常有用,因为它可以大大提高效率和性能,同时减少网络带宽的使用。

在单播通信中,信息从一个节点发送到另一个节点,而在广播通信中,信息从一个节点发送到网络中的所有节点。多播则介于这两者之间,信息从一个节点发送到一组特定的节点。这种方式特别适合于需要向一组特定的主机发送信息的场景,例如在线视频会议或实时数据共享。

多播的实现依赖于D类IP地址,范围从224.0.0.0到239.255.255.255。这些地址被划分为局部链接多播地址、预留多播地址和管理权限多播地址。主机可以向路由器请求加入或退出某个多播组,然后路由器和交换机会有选择地复制并传输数据,只将数据传输给组内的主机。

多播技术的优点包括:

  1. 带宽效率:多播允许数据在同一分组的主机之间共享,节省了网络带宽。

  2. 服务器负载:由于多播协议由接收者的需求来确定是否进行数据流的转发,所以服务器端的带宽是常量,与客户端的数量无关。

  3. 广域网支持:与广播不同,多播可以在广域网,如Internet上进行。

然而,多播技术也有一些缺点:

  1. 无纠错机制:多播与单播相比没有纠错机制,当发生错误的时候难以弥补,但是可以在应用层来实现此种功能。

  2. 网络支持:多播的网络支持存在缺陷,需要路由器及网络协议栈的支持。

总的来说,多播技术是一种强大的网络通信机制,它在许多场景中都非常有用,如网上视频、网上会议等。然而,要有效地使用多播,需要理解其工作原理,并确保网络设备和协议栈正确地支持多播。

第二章: 广域网的多播

当然,我很乐意帮助你深入理解广域网的多播和多播地址。

多播是一种网络通信机制,它允许一个节点(发送者)向一组节点(接收者)发送信息。这种方式在网络编程中非常有用,因为它可以大大提高效率和性能。

在IP网络中,多播地址被定义为D类IP地址,范围从224.0.0.0到239.255.255.255。这些地址被划分为三类:

  1. 局部链接多播地址:这个范围是从224.0.0.0到224.0.0.255。这些地址主要用于网络设备之间的本地通信,例如路由器之间的通信。这些地址的数据包不会被路由器转发到其他网络。

  2. 预留多播地址:这个范围是从224.0.1.0到238.255.255.255。这些地址可以在全球范围内使用,例如在Internet上。这意味着,如果你的应用程序需要向全球的多个节点发送信息,你可以使用这个范围内的地址。

  3. 管理权限多播地址:这个范围是从239.0.0.0到239.255.255.255。这些地址类似于私有IP地址,只能在特定的组织或企业内部使用。这些地址的数据包不能在Internet上路由,因此可以用来限制多播的范围。

在使用多播地址时,你需要注意一些事情。首先,你需要确保你的网络设备(如路由器和交换机)支持多播,并且已经正确配置。其次,你需要选择正确的多播地址,以确保你的信息能够正确地发送到目标节点。

希望这个解释能帮助你更深入地理解广域网的多播和多播地址。如果你还有其他问题,欢迎随时向我提问。

第三章: 多播的编程

当然,我很乐意帮助你深入理解多播编程。以下是我对这个主题的详细解释:

多播是一种在网络中发送信息的方式,它允许一个节点向一组节点发送信息,而不是单独向每个节点发送。这种方式在网络编程中非常有用,因为它可以大大提高效率和性能。

在多播编程中,我们使用一些特殊的套接字选项来控制多播行为。这些选项通常在IP层设置,因为多播是在IP层实现的。

  1. IP_MULTICAST_TTL:这个选项用于设置多播数据包的生存时间(TTL)。TTL是一个在0到255之间的值,它决定了数据包可以通过多少个路由器。每当数据包通过一个路由器,其TTL就会减1,当TTL达到0时,数据包就会被丢弃。这个选项可以防止多播数据包在网络中无限制地传播。

  2. IP_MULTICAST_IF:这个选项用于设置默认的多播接口。多播数据包将从这个接口发送,其他接口将忽略这些数据包。

  3. IP_MULTICAST_LOOP:这个选项用于控制是否允许多播数据包在本地回环。如果设置为1,数据包将在本地回环;如果设置为0,数据包将不会在本地回环。

  4. IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP:这两个选项用于控制节点是否加入或离开一个多播组。当一个节点加入一个多播组后,它就可以接收到发送到该组的所有数据包。

在编写多播程序时,我们通常遵循以下步骤:

  1. 创建一个套接字:我们首先需要创建一个套接字来发送和接收数据。

  2. 设置多播参数:然后,我们需要设置多播的参数,如TTL和本地回环。

  3. 加入多播组:接下来,我们需要将节点加入到一个多播组中。

  4. 发送和接收数据:一旦节点加入了一个多播组,它就可以开始发送和接收数据了。

  5. 离开多播组:最后,当节点不再需要接收多播数据时,它可以从多播组中离开。

以下是一个使用C++编写的多播编程示例。这个示例中,我们将创建一个发送者和一个接收者,发送者将向一个多播组发送数据,接收者将接收这些数据。

首先,我们创建一个发送者:

#include <iostream>
#include <string>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    // 创建套接字
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return -1;
    }

    // 设置多播TTL参数
    unsigned char ttl = 1;
    if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
        std::cerr << "Error setting multicast TTL" << std::endl;
        return -1;
    }

    // 设置目标地址
    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr("239.0.0.1"); // 多播地址
    addr.sin_port = htons(12345); // 目标端口

    // 发送数据
    std::string msg = "Hello, Multicast!";
    if (sendto(sock, msg.c_str(), msg.size(), 0, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        std::cerr << "Error sending data" << std::endl;
        return -1;
    }

    std::cout << "Data sent to multicast group" << std::endl;

    return 0;
}

然后,我们创建一个接收者:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main() {
    // 创建套接字
    int sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        std::cerr << "Error creating socket" << std::endl;
        return -1;
    }

    // 绑定到本地地址和端口
    sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY); // 任意本地地址
    addr.sin_port = htons(12345); // 目标端口

    if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        std::cerr << "Error binding socket" << std::endl;
        return -1;
    }

    // 加入多播组
    ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr("239.0.0.1"); // 多播地址
    mreq.imr_interface.s_addr = htonl(INADDR_ANY); // 任意网络接口

    if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        std::cerr << "Error joining multicast group" << std::endl;
        return -1;
    }

    // 接收数据
    char buf[1024];
    memset(buf, 0, sizeof(buf));
    if (recv(sock, buf, sizeof(buf), 0) < 0) {
        std::cerr << "Error receiving data" << std::endl;
        return -1;
    }

    std::cout << "Received data: " << buf << std::endl;

    // 离开多播组
    if (setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
        std::cerr << "Error leaving multicast group" << std::endl;
        return -1;
    }

    return 0;
}

第四章:深入理解Linux内核中的多播

在Linux内核中,多播功能是通过一系列精心设计的数据结构和相应的操作来实现的。本章将深入探讨这些数据结构,包括struct ip_mc_sockliststruct ip_mreqnstruct ip_sf_socklist,以及如何通过IP_ADD_MEMBERSHIPIP_DROP_MEMBERSHIP选项来操作这些数据结构,从而实现多播功能。

4.1 多播的核心数据结构:ip_mc_socklist

在Linux内核中,多播是通过struct ip_mc_socklist数据结构来实现的。这个数据结构连接了多播的各个方面,包括多播的TTL(Time To Live)、是否启用多播回环、多播设备序号、多播地址以及多播群组。

4.2 加入和离开多播组:IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP

在Linux中,我们可以通过IP_ADD_MEMBERSHIP选项来将一个本地IP地址加入到一个多播组。这个过程主要包括将用户数据复制到内核、检查多播IP地址的合法性、查找对应的网络接口、检查多播列表中是否已存在该多播地址,以及将该多播地址加入到列表中。

相反,我们可以通过IP_DROP_MEMBERSHIP选项来将一个本地IP地址从一个多播组中移除。这个过程主要包括将用户数据复制到内核、查找对应的网络接口、检查多播列表中是否已存在该多播地址,以及将该多播地址从源地址和多播列表中移除。

4.3 源过滤:ip_sf_socklist

在Linux内核中,我们可以通过struct ip_sf_socklist数据结构来实现源过滤。这个数据结构包含了一个源地址列表,以及列表中源地址的数量和列表的最大容量。我们可以通过这个数据结构来控制哪些源的多播数据报被接收,哪些源的多播数据报被排除。

通过深入理解这些数据结构和操作,我们可以更好地理解Linux内核中的多播功能,以及如何在我们的应用中使用多播。在下一章中,我们将探讨如何在实际应用中使用Linux的多播功能。

一个多播服务器端的示例

下面是一个改进后的多播服务器端的示例。这个示例程序将持续向多播IP地址"224.0.0.88"的8888端口发送数据"BROADCAST TEST DATA",每发送一次间隔5s。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MCAST_PORT 8888
#define MCAST_ADDR "224.0.0.88"
#define MCAST_DATA "BROADCAST TEST DATA"
#define MCAST_INTERVAL 5

int main(void)
{
    int sockfd;
    struct sockaddr_in mcast_addr;

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    // 初始化多播地址
    memset(&mcast_addr, 0, sizeof(mcast_addr));
    mcast_addr.sin_family = AF_INET;
    mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);
    mcast_addr.sin_port = htons(MCAST_PORT);

    // 循环发送多播数据
    while (1)
    {
        int n = sendto(sockfd, MCAST_DATA, sizeof(MCAST_DATA), 0, (struct sockaddr*)&mcast_addr, sizeof(mcast_addr));
        if (n == -1)
        {
            perror("sendto");
            exit(EXIT_FAILURE);
        }

        // 等待一段时间
        sleep(MCAST_INTERVAL);
    }

    close(sockfd);

    return 0;
}

这个程序的流程如下:

在这里插入图片描述

  1. 创建套接字。
  2. 初始化多播地址。
  3. 设置协议族为AF。
  4. 设置多播IP地址。
  5. 设置多播端口。
  6. 开始循环,向多播地址发送数据。
  7. 等待一段时间。
  8. 回到步骤6。

这个程序的改进之处在于,它更加简洁,更加注重错误处理,确保在发生错误时能够及时退出并给出错误信息。同时,它也更加注重资源管理,确保在程序结束时关闭套接字。

一个多播客户端的示例

下面是一个改进后的多播客户端的示例。这个示例程序将加入多播组"224.0.0.88",监听端口8888,接收并打印出从多播组收到的数据。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

#define MCAST_PORT 8888
#define MCAST_ADDR "224.0.0.88"
#define MCAST_INTERVAL 5
#define BUFF_SIZE 256

int main(void)
{
    int sockfd;
    struct sockaddr_in local_addr;
    struct ip_mreq mreq;
    char buff[BUFF_SIZE];
    int n;

    // 创建套接字
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }

    // 初始化本地地址
    memset(&local_addr, 0, sizeof(local_addr));
    local_addr.sin_family = AF_INET;
    local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    local_addr.sin_port = htons(MCAST_PORT);

    // 绑定socket
    if (bind(sockfd, (struct sockaddr*)&local_addr, sizeof(local_addr)) == -1)
    {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    // 设置回环许可
    int loop = 1;
    if (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) == -1)
    {
        perror("setsockopt: IP_MULTICAST_LOOP");
        exit(EXIT_FAILURE);
    }

    // 加入多播组
    mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
    {
        perror("setsockopt: IP_ADD_MEMBERSHIP");
        exit(EXIT_FAILURE);
    }

    // 循环接收多播组的消息
    for (int times = 0; times < 5; times++)
    {
        socklen_t addr_len = sizeof(local_addr);
        memset(buff, 0, BUFF_SIZE);

        n = recvfrom(sockfd, buff, BUFF_SIZE, 0, (struct sockaddr*)&local_addr, &addr_len);
        if (n == -1)
        {
            perror("recvfrom");
            exit(EXIT_FAILURE);
        }

        // 打印信息
        printf("Recv %dst message from server: %s\n", times, buff);

        // 等待一段时间
        sleep(MCAST_INTERVAL);
    }

    // 退出多播组
    if (setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
    {
        perror("setsockopt: IP_DROP_MEMBERSHIP");
        exit(EXIT_FAILURE);
    }

    close(sockfd);

    return 0;
}

这个程序的流程如下:

在这里插入图片描述

  1. 创建套接字。
  2. 初始化本地地址。
  3. 绑定socket。
  4. 设置回环许可。
  5. 加入多播组。
  6. 开始循环,接收数据。
  7. 打印信息。
  8. 等待一段时间。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/605127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习(Pytorch):Softmax回归

Softmax简介 Softmax回归是一个用于多类分类问题的线性模型&#xff0c;它是从Logistic回归模型演变而来的。Softmax回归与Logistic回归类似&#xff0c;但是输出不再是二元的&#xff0c;而是多类的。Softmax回归引入了softmax激活函数来将输出转换为合理的概率分布。与线性回…

HCIE-Cloud Computing LAB备考--第五题:规划--Type13练习--记忆技巧+默写

对LLD表,交换机接口表,ensp配置进行练习,如下图,设置答案和空白表,进行默写,汇总自己的容易犯的错误 LLD表默写思路 交换机接口配置表默写思路 以Type3为例,同颜色复制即可,共用ST.P0是A25,ST.P2是A21,FS是ST.P0是A21,ST.P2是A21。 ensp配置默写思路 特点: 所…

一步一步学习 Stable Diffusion

一步一步学习 Stable Diffusion 0. 背景1. 安装2. 汉化3. 安装 sd-webui-controlnet 插件4. 安装 sd-webui-segment-anything 插件5. 安装 ultimate-upscale 插件6. 安装 SadTalker 插件7. 下载和配置 VAE 模型8. 使用 ChilloutMix 模型99. 未完待续 0. 背景 网上看了很多 Sta…

priority_queue(优先级队列)

priority_queue 1. priority_queue的介绍及使用1.1 priority_queue的介绍1.2 priority_queue的使用1.2.1 constructor(构造)1.2.2 empty1.2.3 size1.2.4 top1.2.5 emplace1.2.6 push、pop、swap 1.3 数组中第K个大的元素 2.priority_queue的深度剖析及模拟实现 1. priority_que…

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试

Makerbase SimpleFOC ESP32例程4 双电机闭环速度测试 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运转。…

柔性作业车间调度

1柔性车间作业调度 个工件 要在 台机器 上加工。每个工件包含一道或多道工序&#xff0c;工序顺序是预先确定的&#xff0c;每道工序可以在多台不同加工机器上进行加工&#xff0c;工序的加工时间随加工机器的不同而不同。调度目标是为每道工序选择最合适的机器、确定每台机器…

【C语言】语言篇——数组和字符串

C站的小伙伴们&#xff0c;大家好呀&#x1f61d;&#x1f61d;&#xff01;我最近在阅读学习刘汝佳老师的《算法竞赛入门经典》&#xff0c;今天将整理本书的第三章——数组和字符串的一些习题&#xff0c;本章习题较多&#xff0c;下选取部分习题进行练习总结&#xff0c;在这…

200道面试题(附答案)

最近有不少小伙伴跑来咨询&#xff1a; 想找网络安全工作&#xff0c;应该要怎么进行技术面试准备&#xff1f;工作不到 2 年&#xff0c;想跳槽看下机会&#xff0c;有没有相关的面试题呢&#xff1f; 为了更好地帮助大家高薪就业&#xff0c;今天就给大家分享两份网络安全工…

ubuntu20.04 ffmpeg mp4转AES加密的m3u8分片视频

样本视频(时长2分35秒): 大雄兔_百度百科 大雄兔_百度百科不知大家否看过世界上第一部开源电影&#xff1a;Elephants Dream&#xff08;大象之梦&#xff09;。这是一部由主要由开源软件Blender制作的电影短片&#xff0c;证明了用开源软件也能制作出效果媲美大公司的作品。…

1-9 随机算法【手写+Xmind笔记】

文章目录 1 Min-Cut【手写笔记】1.1 问题描述1.2 解决方案1.3 概率证明 2 赠券收集【手写笔记】3 快排期望【手写笔记】4 素数性质【手写笔记】4.1 基本性质4.2 解决方案4.3 群论4.4 费马小定理4.5 Miller Rabin素性测试 5-6 力矩与偏差【手写笔记】5.1 基础不等式5.2 矩生成函…

[图表]pyecharts模块-柱状图

[图表]pyecharts模块-柱状图 先来看代码&#xff1a; from pyecharts.charts import Bar from pyecharts.faker import Faker from pyecharts.globals import ThemeTypec (Bar({"theme": ThemeType.MACARONS}).add_xaxis(Faker.choose()).add_yaxis("商家A&q…

Spring 核心概念之一 IoC

前言 欢迎来到本篇文章&#xff01;通过上一篇什么是 Spring&#xff1f;为什么学它&#xff1f;的学习&#xff0c;我们知道了 Spring 的基本概念&#xff0c;知道什么是 Spring&#xff0c;以及为什么学习 Spring。今天&#xff0c;这篇就来说说 Spring 中的核心概念之一 Io…

day2 -- 数据库的安全管理和维护

brief 访问控制的目的不仅仅是防止用户的恶意企图。数据梦魇更为常见的是无意识错误的结果&#xff0c;如错打MySQL语句&#xff0c;在不合适的数据库中操作或其他一些用户错误。通过保证用户不能执行他们不应该执行的语句&#xff0c;访问控制有助于避免这些情况的发生。管理…

Makerbase SimpleFOC ESP32 例程6 双电机闭环位置力矩互控

Makerbase SimpleFOC ESP32 例程6 双电机闭环位置力矩互控 第一部分 硬件介绍 1.1 硬件清单 序号品名数量1ESP32 FOC V1.0 主板12YT2804电机2312V电源适配器14USB 线156pin杜邦线2 注意&#xff1a;YT2804是改装的云台无刷电机,带有AS5600编码器&#xff0c;可实现360连续运…

Go 字节跳动—从需求到上线全流程

走进后端开发流程 整个课程会带大家先从理论出发&#xff0c;思考为什么有流程 大家以后工作的团队可能不一样&#xff0c;那么不同的团队也会有不同的流程&#xff0c;这背后的逻辑是什么 然后会带大家按照走一遍从需求到上线的全流程&#xff0c;告诉大家在流程的每个阶段&am…

angular环境安装 (含nodejs详细安装步骤)

在安装本次环境之前&#xff0c;需要先把本机上的nodejs环境卸载&#xff0c;环境变量手动删除&#xff01;安装过程种环境才不会产生副作用&#xff01;实际项目安装的一次记录&#xff0c;踩了太多坑&#xff0c;记录一下&#xff0c;旨在记录&#xff01;项目需要两个不用版…

常用设计模式介绍~~~ Java实现 【概念+案例+代码】

前言 想要读懂源码、让自己的代码写的更加优雅&#xff0c;重构系统等。理解设计模式的思想&#xff0c;可以让我们事半功倍。以下稍微整理了常用的设计模式、每一种设计模式都有详细的概念介绍、案例说明、代码实例、运行截图等。这里给出目录导航。 目录 一、创建型模式 【一…

现在的面试把我卷崩溃了....

现在的面试也太卷了&#xff0c;前几天组了一个软件测试面试的群&#xff0c;没想到效果直接拉满&#xff0c;看来大家对面试这块的需求还是挺迫切的。昨天我就看到群友们发的一些面经&#xff0c;感觉非常有参考价值&#xff0c;于是我就问他还有没有。 结果他给我整理了一份…

Linux命令学习之cd

cd是进入某个目录的命令。man 1 cd看一下cd的使用说明。 发现cd是一个Shell内置命令。内置命令可以使用help 命令行来看一下帮助&#xff0c;比如help cd就可以看一下cd的帮助。 图中的[dir]就是参数&#xff0c;这个参数是目录名&#xff0c;比如可以使用cd /可以进入根目录…

外包派遣3年华为,合同结束转正,转正后工资12k-15k,13薪,包三餐,值得去吗?

“但凡有点机会&#xff0c;千万别去外包! ” 在程序员圈子里面&#xff0c;外包程序员似乎永远处于一个尴尬的角色&#xff0c;如果你说他们不是程序员吧&#xff0c;他们也是程序员。应该说是外包这个词比较尴尬吧。赶着和正式工一样的伙&#xff0c;待遇缺天差地别&#xf…