UDP多播

1 、多播的概念

多播,也被称为组播,是一种网络通信模式,其中数据的传输和接收仅在同一组内进行。多播具有以下特点:

  1. 多播地址标识一组接口:多播使用特定的多播地址,该地址标识一组接收数据的接口。发送到多播地址的数据包将被传递给属于该组的所有接口。

  2. 适用于广域网使用:与广播通信通常局限于局域网内不同,多播可以用于广域网环境。这使得多播成为一种在大型网络中分发数据的高效方式,因为它只将数据发送给需要的接收者。

  3. 在IPv4中是可选的:在IPv4网络中,多播支持是可选的,这意味着并非所有网络都支持多播。然而,在IPv6中,多播是强制要求的,所有IPv6网络都必须支持多播。

多播地址

IPv4的D类地址是多播地址

十进制:224.0.0.1~239.255.255.254

十六进制:E0.00.00.01~EF.FF.FF.FE

多播地址向以太网MAC地址的映射

 

2 、多播工作过程 

比起广播,多播具有可控性,只有加入多播组的接收者才可以接收数据,否则接收不到

 3 、多播流程

发送者

  1. 创建套接字:使用socket()函数创建一个数据报套接字(SOCK_DGRAM),以支持UDP通信。
  2. 发送数据:使用sendto()函数向多播地址发送数据。多播地址是一个特殊的IP地址,用于表示一组接收者。

接收者

  1. 创建套接字:与发送者一样,使用socket()函数创建一个数据报套接字(SOCK_DGRAM)。
  2. 加入多播组:使用setsockopt()函数将套接字设置为加入多播组。这通常需要设置IP_ADD_MEMBERSHIP选项,并提供要加入的多播组的地址和接口。
  3. 绑定套接字:使用bind()函数将套接字与一个本地地址和端口号绑定。这将使套接字能够接收发送到该地址和端口的数据。
  4. 接收数据:使用recvfrom()函数接收发送到绑定地址和端口的数据。该函数将返回发送者的信息,包括其IP地址和端口号。

4 、多播地址结构体

在IPv4因特网域(AF_INET)中,多播地址结构体用如下结构体ip_mreq表示

5 、多播套接口选项 

#include <sys/socket.h>int setsockopt(int socket, int level, int option_name,const void *option_value, socklen_t option_len);

功能:设置一个套接字的选项(属性)。

参数:

  • socket:文件描述符,表示要设置选项的套接字。
  • level:协议层次,指定要设置选项的协议层次。对于多播组的操作,使用IPPROTO_IP表示IP层次。
  • option_name:选项的名称。对于加入多播组,使用IP_ADD_MEMBERSHIP选项。
  • option_value设置的选项的值。对于IP_ADD_MEMBERSHIP选项,需要提供一个指向struct ip_mreq结构的指针。该结构包含以下两个字段:
    • imr_multiaddr:表示要加入的多播组的IP地址。
    • imr_interface:表示要接收多播数据的主机接口地址。通常使用INADDR_ANY表示任意主机地址,系统会自动选择合适的接口。
  • option_len:表示option_value的长度,即struct ip_mreq结构的大小。

返回值:

  • 成功:返回0。
  • 失败:返回-1,并设置errno以指示错误原因。

通过调用setsockopt()函数并将option_name设置为IP_ADD_MEMBERSHIP,接收者可以加入指定的多播组,并接收发送到该多播组的数据。

6、 加入多播组示例 

发送者: 

#include <stdio.h> //printf
#include <stdlib.h> //exit
#include <sys/types.h>
#include <sys/socket.h> //socket
#include <netinet/in.h> //sockaddr_in
#include <arpa/inet.h> //htons inet_addr
#include <unistd.h> //close
#include <string.h>int main(int argc, char const *argv[])
{if(argc < 3){fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);exit(1);}int sockfd; //文件描述符struct sockaddr_in groupcastaddr; //服务器网络信息结构体socklen_t addrlen = sizeof(groupcastaddr);//第一步:创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//第二步:填充组播信息结构体groupcastaddr.sin_family = AF_INET;groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]); //224.x.x.x - 239.x.x.xgroupcastaddr.sin_port = htons(atoi(argv[2]));//第三步:进行通信char buf[128] = "";while(1){fgets(buf, sizeof(buf), stdin);buf[strlen(buf) - 1] = '\0';   //"hello\n"-->"hello\0"if(sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&groupcastaddr, addrlen) < 0){perror("fail to sendto");exit(1);}}return 0;
}

它实现了一个多播发送者,可以向特定的多播IP地址和端口发送数据。在运行该程序时,需要提供两个命令行参数:要发送数据的多播IP地址和端口号。程序会创建一个UDP套接字,并填充一个包含目标多播地址和端口的结构体。然后,程序会进入一个无限循环,从标准输入读取数据,并将数据通过sendto函数发送到指定的多播地址和端口。需要注意的是,多播地址的范围是224.x.x.x到239.x.x.x。 

接收者:

1 #include <stdio.h> //printf2 #include <stdlib.h> //exit3 #include <sys/types.h>4 #include <sys/socket.h> //socket5 #include <netinet/in.h> //sockaddr_in6 #include <arpa/inet.h> //htons inet_addr7 #include <unistd.h> //close8 #include <string.h>910 int main(int argc, char const *argv[])11 {12    if(argc < 3)13    {14        fprintf(stderr, "Usage: %s <ip> <port>\n", argv[0]);15        exit(1);16    }1718    int sockfd; //文件描述符
19    struct sockaddr_in groupcastaddr; 
20    socklen_t addrlen = sizeof(groupcastaddr);2122    //第一步:创建套接字
23    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)24    {25        perror("fail to socket");26        exit(1);27    }2829    //第二步:设置为加入多播组
30    struct ip_mreq mreq;31    mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);32    mreq.imr_interface.s_addr = INADDR_ANY;33    if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)34    {35        perror("fail to setsockopt");36        exit(1);37    }3839    //第三步:填充组播信息结构体
40    groupcastaddr.sin_family = AF_INET;41    groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]);  //224.x.x.x ‐ 239.x.x.x42    groupcastaddr.sin_port = htons(atoi(argv[2]));4344    //第四步:将套接字与广播信息结构体绑定
45    if(bind(sockfd, (struct sockaddr *)&groupcastaddr, addrlen) < 0)46    {47        perror("fail to bind");48        exit(1);49    }5051    //第五步:进行通信
52    char text[32] = "";53    struct sockaddr_in sendaddr;5455    while(1)56    {57        if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&sendaddr, &addrlen) < 0)
58        {59            perror("fail to recvfrom");60            exit(1);61        }62        
63        printf("[%s ‐ %d]: %s\n", inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), text);64    }6566    return 0;67 }

它实现了一个多播接收者,可以接收来自特定多播IP地址和端口的数据。在运行该程序时,需要提供两个命令行参数:要接收数据的多播IP地址和端口号。程序会创建一个UDP套接字,并使用setsockopt函数将套接字设置为加入指定的多播组。然后,程序会填充一个包含目标多播地址和端口的结构体,并将套接字绑定到该结构体上。接下来,程序会进入一个无限循环,使用recvfrom函数接收数据,并将数据的来源IP地址、端口号和内容打印出来。需要注意的是,多播地址的范围是224.x.x.x到239.x.x.x。

 执行结果

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实现红黑树

目录 红黑树的概念 红黑树的节点结构定义 红黑树的插入 红黑树的验证 实现红黑树完整代码 红黑树的概念 红黑树 &#xff0c;是一种 二叉搜索树 &#xff0c;但 在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是 Red 或 Black 。 通过对 任何一条从根到叶子的…

Leetcode39.组合总和

文章目录 题目描述解题思路重复子集剪枝 代码 题目 参考题解 题目描述 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返…

【JavaSE】/*初识Java*/

目录 一、了解 Java 语言 二、Java 语言的重要性 2.1 使用程度 2.2 工作领域 三、Java 语言的特性 四、Java 的基础语法 五、可能遇到的错误 六、第一个 java 程序代码解析 七、Java 注释 八、Java 标识符 九、Java 关键字 一、了解 Java 语言 Java 是由 Sun Micr…

图论(洛谷刷题)

目录 前言&#xff1a; 题单&#xff1a; P3386 【模板】二分图最大匹配 P1525 [NOIP2010 提高组] 关押罪犯 P3385 【模板】负环 P3371 【模板】单源最短路径&#xff08;弱化版&#xff09; SPFA写法 Dij写法&#xff1a; P3385 【模板】负环 P5960 【模板】差分约束…

【iOS开发】—— 初识锁

【iOS开发】—— 初识锁 线程安全锁的种类自旋锁定义原理自旋锁缺点OSSpinLock&#xff08;自旋锁&#xff09; 互斥锁os_unfair_lockpthread_mutexNSLockNSRecusiveLockSemaphore信号量synchronized 总结两种之间的区别和联系&#xff1a; 线程安全 当一个线程访问数据的时候…

双向冒泡法,可以只求最大最小值

int BiBubbleSort(int Arr[],int n,int maxnum){int left0,rightn-1;int i;bool notDone true;int temp;if(n<2)return -1;while(left<right&&notDone){ notDone false; //设置未发生交换标志 for(ileft;i<right;i){if(Arr[i]>Arr[i1]){//swap(Arr[…

Python-VBA函数之旅-staticmethod函数

目录 一、staticmethod函数的常见应用场景 二、staticmethod函数使用注意事项 三、如何用好staticmethod函数&#xff1f; 1、staticmethod函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://blog…

HackMyVM-VivifyTech

目录 信息收集 arp nmap nikto whatweb WEB web信息收集 wpscan feroxbuster hydra 提权 系统信息收集 横向渗透 git提权 get root 信息收集 arp ┌──(root㉿0x00)-[~/HackMyVM] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 08:00:27:9d:6d:7b, …

【密评】 | 商用密码应用安全性评估从业人员考核题库(9/58)

Hill密码是重要古典密码之一&#xff0c;其加密的核心思想的是&#xff08;&#xff09;。 A.线性变换 B.非线性变换 C.循环移位 D.移位 著名的Kerckhoff原则是指&#xff08;&#xff09;。 A.系统的保密性不但依赖于对加密体制或算法的保密&#xff0c;而且依赖于密钥 B.系统…

即插即用篇 | YOLOv8 引入 Strip Pooling | 重新思考场景解析的空间池化

本改进已集成到 YOLOv8-Magic 框架。 空间池化已被证明在捕获像素级预测任务的长距离上下文信息方面非常有效,如场景解析。在本文中,我们超越了通常具有N N规则形状的常规空间池化,重新思考空间池化的构成,引入了一种新的池化策略,称为条带池化,它考虑了一个长而窄的核,…

C++ 中的 lambda 表达式

1.概念 lambda表达式实际上是一个匿名类的成员函数&#xff0c;该类由编译器为lambda创建&#xff0c;该函数被隐式地定义为内联。因此&#xff0c;调用lambda表达式相当于直接调用匿名类的operator()函数&#xff0c;这个函数可以被编译器内联优化&#xff08;建议&#xff0…

C++的数据结构(二)

一、链表的基本概念 链表&#xff08;Linked List&#xff09;是一种物理存储单元上非连续的、非顺序的线性数据结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列节点&#xff08;链表中每一个元素称为节点&#xff09;组成&#xff0c;节点…

py黑帽子学习笔记_网络编程工具

tcp客户端 socket.AF_INET表示使用标准IPV4地址和主机名 SOCK_STREAM表示这是一个TCP客户端 udp客户端 udp无需连接&#xff0c;因此不需要client.connect这种代码 socket.SOCK_DGRAM是udp的 tcp服务端 server.listen(5)表示设置最大连接数为5 发现kill server后端口仍占用…

牛客NC404 最接近的K个元素【中等 二分查找+双指针 Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/b4d7edc45759453e9bc8ab71f0888e0f 知识点 二分查找&#xff1b;找到第一个大于等于x的数的位置idx;然后从idx开始往两边扩展Java代码 import java.util.*;public class Solution {/*** 代码中的类名、方法名、…

Shell编程规范与变量

Shell 什么是Shell&#xff1f; 就是与内核沟通的界面、应用程序等等。比如你要播放音乐&#xff0c;你的计算机通过你在Shell输入的打开音乐的命令&#xff0c;Shell在告诉操作系统的内核用户希望打开音乐&#xff0c;内核在通过cpu调度、内存管理、磁盘输入输出等工作&#…

JAVA课程设计

一&#xff1a;Java连接mysql数据库 1.1点击进入mysql jar包下载官网 MySQL :: MySQL Community Downloads 将下载好的压缩包进行解压 解压之后下图就是连接数据库所用到的jar包&#xff1a; 将jar包复制到IDEA所用的项目下&#xff0c;放置jar包的目录为lib&#xff0c;需要…

NSS刷题

[SWPUCTF 2021 新生赛]jicao 类型&#xff1a;PHP、代码审计、RCE 主要知识点&#xff1a;json_decode()函数 json_decode()&#xff1a;对JSON字符串解码&#xff0c;转换为php变量 用法&#xff1a; <?php $json {"ctf":"web","question"…

安装Nox夜神模拟器关闭了HyperV后Docker运行不了怎么办?

1.背景 为了模拟真机&#xff0c;尝试安装了Nox夜神模拟器&#xff0c; 安装过程要求关闭Hyper-V。当时只是在程序安装卸载中关闭了系统服务。以为到时勾选上就好了。操作路径&#xff1a;控制面板\所有控制面板项\程序和功能\启用或关闭Windows功能\Hyper-V。 后来卸载掉了夜神…

FreeRTOS的列表和列表项 list.c文件详解

列表、列表项的定义以及初始化 列表相当于链表&#xff0c;列表项相当于节点&#xff0c;FreeRTOS中的列表相当于一个双向环形链表。 列表使用指针指向列表项。一个列表&#xff08;list&#xff09;下面可能有很多个列表项&#xff08;list item&#xff09;&#xff0c;每个…

vivado仿真readmemb函数相对路径

目前常用的vivado工程的结构如下所示 prj-name|-xxx|-prj.sim|-sim_1|-behav|-modelsim|-tb_prj.do|-xsim|-prj.srcs|-sim_1|-new|-tb_prj.v|-tb_prj_mem.txt一般来说我们创建的testbench文件和新建的txt文件都会放在srcs->sim_1->new这个路径下面&#xff0c;但是我们在…