九:多播和广播

news/2024/7/27 7:49:11/文章来源:https://blog.csdn.net/weixin_44715186/article/details/136309126

1 多播

&emsp 多播(Multicast )方式的数据传输是基于UDP完成的。 因此,与UDP服务器端/客户端的实现方式非常接近。 区别在于, UDP数据传输以单一目标进行,而多播数据同时传递到加入(注册)特定组的大量主机。 换言之,采用多播方式时,可以同时向多个主机传递数据。

1.1 多播的数据传输方式及流量方面的优点

多播的数据传输特点如下:

  • 多播服务端针对特定多播组,只发送一次数据。
  • 即使只发送一次数据,但该组内的所有客户端都会接收数据。
  • 多播组数可在IP地址范围内任意增加。
  • 加入特定组即可接收发往该多播的数据。

  多播是D类IP地址(224.0.0.0~239.255.255.255),"加入多播组"可以理解为在D类IP地址中,我希望接收发往目标239.234.218.234的多播数据
  多播是基于UDP完成的,也就是说,多播数据包的格式与UDP数据包相同。不同的是,向网络发送一个多播数据包时,路由器将复制该数据包并传递到多个主机。多播需要借助路由器完成,如下图所示:

  不要觉得频繁复制同一数据包,会不利于网络流量,因为不会向同一区域发送多个相同的数据包。相当于羊村的100之羊,从很远的地方定了一批相同的订单,使用TCP/UDP需要送100次,但是使用多播,只需要送一次到羊村门口,然后村里驿站复制100份然后给小羊就行。基于这种特性,多播主要用于“多媒体数据的实时传输”。
  注意:虽然理论上可以完成多播通信,但不少路由器并不支持多播,或即便支持也因网络拥堵问题故意阻断多播。因此为了在不支持多播的路由器中完成多播通信,也会使用隧道技术。

1.2 路由和TTL,以及加入组的方法

  为了传递多播数据包,必须设置TTL(Time to Live),这是决定“数据包传递距离”的主要因素。TTL用整数表示,并且每经过一个路由器就减1,TTL变为0时,该数据包将无法传递被销毁。因此,TTL值设置过大将影响网络流量,设置国小会无法传递到目标,注意。
  TTL设置方法是通过此节:套接字可选项完成的。与TTL相关的协议层为IPPROTO_IP,选项名为IP_MULTICAST_TTL。具体设置如下:

int send_sock;
int time_live = 64;
...
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
setsockopt(send_sock, IPPROTO, IP_MULTICAST_TTL, (void*)&time_live, sizeof(time_live));
...

另外,加入多播组也通过设置套接字选项完成,协议层为IPPROTO_IP,选项为IP_ADD_MEMBERSHIP。具体代码如下:

int recv_sock;
struct ip_mreq join_adr;
...
recv_sock = socket(FP_INET, SOCK_DGRAM, 0);
...
join_adr.imr_multiaddr.saddr = "多播组地址信息";
join_adr.imr_interface.saddr = "加入多播组的主机地址信息";
setsockopt(recv_sock, IPPROTO, IP_ADD_MEMBERSHIP, (void*)&join_adr, sizeof(join_adr));

ip_mreq的结构体定义如下:

struct ip_mreq
{struct in_addr imr_multiaddr;struct in_addr imr_interface;
}

1.3 实现多播Sender 和 Receiver

  多播中使用“发送者”和“接收者”替代服务端和客户端,此处Sender是多播数据的发送主体,Receiver是多播数据的发送主体,Receiver需要加入多播组接收数据。下面给出示例,示例背景如下:

  • Sender:向AAA组广播文件中保存的新闻消息
  • Receiver:接收传递到AAA组的新闻信息
    在这里插入图片描述

news_sender.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>#define TTL 64
#define BUF_SIZE 30void ErrorHandler(char* message) {fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]) {int send_sock;struct sockaddr_in mul_adr;int time_live = TTL;FILE *fp;char buf[BUF_SIZE];if (argc != 3) {printf("Usage : %s <IP><PORT>\n", argv[0]);exit(1);}//多播通信基于UDPsend_sock = socket(PF_INET, SOCK_DGRAM, 0);//设置传输数据的目标地址信息memset(&mul_adr, 0, sizeof(mul_adr));mul_adr.sin_family = AF_INET;mul_adr.sin_addr.s_addr = inet_addr(argv[1]);mul_adr.sin_port = htons(atoi(argv[2]));//设置TTL信息setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*)&time_live, sizeof(time_live));if (fp = fopen("news.txt", "r") == NULL) {ErrorHandler("fopen() error");}//实际传输数据的区域。while (!feof(fp)) {fgets(buf, BUF_SIZE, fp);sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&mul_adr, sizeof(mul_adr));sleep(2); //纯纯添加时间间隔,没意义的}fclose(fp);close(send_sock);return 0;
}

news_receiver.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netinet/in.h>#define BUF_SIZE 30void ErrorHandler(char* message) {fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]) {if (argc != 3) {printf("Usage : %s <GroupIP><PORT> \n", argv[0]);exit(1);}int recv_sock;int str_len;char buf[BUF_SIZE];struct sockaddr_in adr;struct ip_mreq join_adr;recv_sock = socket(PF_INET, SOCK_DGRAM, 0);memset(&adr, 0, sizeof(adr));adr.sin_family = AF_INET;adr.sin_addr.s_addr = inet_addr(INADDR_ANY);adr.sin_port = htons(atoi(argv[2]));if (bind(recv_sock, (struct sockaddr*)&adr, sizeof(adr)) == -1) {ErrorHandler("bind error");}//初始化结构体ip_mreqjoin_adr.imr_multiaddr.s_addr = inet_addr(argv[1]); //初始化多播组地址join_adr.imr_interface.s_addr = htonl(INADDR_ANY);//加入多播组setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&join_adr, sizeof(join_adr));while (1) {//不知道传输数据的主机地址信息,所以传0str_len = recvfrom(recv_sock, buf, BUF_SIZE - 1, 0, NULL, 0);if (str_len < 0) {break;}buf[str_len] = 0;fputs(buf, stdout);}close(recv_sock);return 0;
}

2 广播

  广播与多播都是一次性向多个主机发送数据,但是传输数据的范围有区别。多播即使在跨越不同网络的情况下,只要加入多播组就能接收数据。相反,广播只能向同一网络中的主机传输数据。

2.1 广播的理解及实现方法

  广播是向同一网络中所有主机传输数据的方法。广播也是基于UDP完成的,根据传输数据时使用的IP地址的形式,广播分为如下2种。

  • 直接广播
  • 本地广播

  二者在代码上的差别主要在于IP地址。直接广播的IP地址中除了网络地址外,其余主机全部设置为1。例如:希望向网络地址192.12.34中的所有主机传输数据时,可以向192.12.34.255传输。换言之,可以采用直接广播的方式向特定区域内所有主机传输数据。
  反之,在本地广播中使用的IP地址限定为255.255.255.255。例如,192.32.24网络中的主机向255.255.255.255传输数据时,数据将传递到192.32.24网络中的所有主机。
  如何实现Sender和Receiver呢?实际上,如果不仔细观察广播示例中通信时使用的IP地址,则很难与UDP示例进行区分。也就是说,数据通信中使用的IP地址是与UDP示例的唯一区别。默认生成的套接字会阻止广播,因此只需要通过如下代码更改默认设置。

int send_sock;
int bcast = 1;
....
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
....
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void*)&bcast, sizeof(bcast));
....

2.2 实现广播数据的Sender 和 Receiver

在这里插入图片描述
new_sender_brd.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUFF_SIZE 30void ErrorHandler(char* message) {fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]) {if (argc != 3) {printf("Usage: %s <Boardcast IP> <PORT>\n", argv[0]);exit(1);}int send_sock = socket(PF_INET, SOCK_DGRAM, 0);struct sockaddr_in broad_addr;memset(&broad_addr, 0, sizeof(broad_addr));broad_addr.sin_family = AF_INET;broad_addr.sin_addr.s_addr = inet_addr(argv[1]);broad_addr.sin_port = htons(atoi(argv[2]));int bcast = 1;setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void*)&bcast, sizeof(bcast));FILE* fp;if((fp = fopen("news.txt", "r")) == NULL) {ErrorHandler("fopen() error");}char buf[BUFF_SIZE];while(!feof(fp)) {fgets(buf, BUFF_SIZE, fp);sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&broad_addr, sizeof(broad_addr));sleep(2);}close(send_sock);return 0;
}

news_receiver_brd.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>#define BUFF_SIZE 30void ErrorHandler(char* message) {fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char* argv[]) {if (argc != 2) {printf("Usage : %s <PORT> \n", argv[0]);exit(1);}int recv_sock;struct sockaddr_in adr;int str_len;char buf[BUFF_SIZE];recv_sock = socket(PF_INET, SOCK_DGRAM, 0);memset(&adr, 0, sizeof(adr));adr.sin_family  = AF_INET;adr.sin_addr.s_addr = htonl(INADDR_ANY);adr.sin_port = htons(atoi(argv[1]));if (bind(recv_sock, (struct sockaddr*)&adr, sizeof(adr)) == -1) {ErrorHandler("bind error");}while (1) {str_len = recvfrom(recv_sock, buf, BUFF_SIZE-1, 0, NULL, 0);if (str_len < 0) {break;}buf[str_len] = 0;fputs(buf, stdout);}close(recv_sock);return 0;
}
```

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

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

相关文章

DFT应用:计算线性卷积

目录 一、计算两个有限长序列的线性卷积示例 二、无限长序列和有限长序列的卷积(重叠相加法) 实验1&#xff1a;数据实验 实验2&#xff1a;纯净语音加混响(音效) 二、无限长序列和有限长序列的卷积(重叠保留法) 实验1&#xff1a;数据实验 三、小结 一、计算两个有限长序…

[⑥5G NR]: 无线接口协议,信道映射学习

5G系统整体包括核心网、接入网以及终端部分&#xff0c;接入网与终端间通过无线空口协议栈进行连接。无线接口可分为三个协议层&#xff1a;物理层&#xff08;L1&#xff09;、数据链路层&#xff08;L2&#xff09;和网络层&#xff08;L3&#xff09;。 L1&#xff1a;物理…

利用OpenCV 抽取视频的图片,并制作目标检测数据集

1、前言 目标检测中&#xff0c;图片的数据可以从视频中抽取&#xff0c;而OpenCV的VideoCapture可以实现这样的操作 需要的库文件 opencv pip下载&#xff1a; pip install opencv-contrib-python 更换镜像源下载&#xff1a; pip install opencv-contrib-python -i htt…

Linux 理解操作系统

目录 一、冯诺依曼体系结构 二、操作系统 1、概念 2、设计OS的目的 3、定位 4、先描述再组织 5、系统调用和库函数概念 一、冯诺依曼体系结构 计算机&#xff0c;都是有一个个的硬件组件组成&#xff1a; 输入单元&#xff1a;包括键盘, 鼠标&#xff0c;扫描仪, 写板等…

寻找旋转排序数组中的最小值[中等]

优质博文IT-BLOG-CN 一、题目 已知一个长度为n的数组&#xff0c;预先按照升序排列&#xff0c;经由1到n次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组nums [0,1,2,4,5,6,7]在变化后可能得到&#xff1a; 【1】若旋转4次&#xff0c;则可以得到[4,5,6,7,0,1,2…

Flink ExecuteGraph构建源码解析

文章目录 前言ExecutionGraph中的主要抽象概念源码核心代码入口源码核心流程&#xff1a; 前言 在JobGraph构建过程中分析了JobGraph的构建过程&#xff0c;本文分析ExecutionGraph的构建过程。JobManager(JobMaster) 根据 JobGraph 生成 ExecutionGraph。ExecutionGraph是JobG…

C++前置声明的学习

【C】C中前置声明的应用与陷阱_前置生命如何使用-CSDN博客 首先&#xff0c;这样写会报错&#xff1a; #pragma once #include "A.h" class B {A a; public:B(void);~B(void); };#include "B.h" B::B(void) { }B::~B(void) { } #pragma once #include &…

URL?后参数有特殊字符问题

前端对于URL的参数不做处理 不处理、用URLDecoder.decode()处理、用URLEncoder.encode()处理、用URLEncoder.encode()处理后再用URLDecoder.decode()处理 结果 前端对于URL的参数用encodeURIComponent(‘XF-OPPZZD-26*316’)处理 结果 前端不处理有&字符时 结果会把后…

前端网络请求异步处理——Promise使用记录

Promise是ES6中新增的一个处理复杂异步请求的工具&#xff0c;其主要形式为&#xff1a; const baseUrl http://localhost:80 export const $request (param {}) > {console.log(请求参数, param)return new Promise((resolve, reject) > {wx.request({url: baseUrl …

海外服务器被DDOS攻击了该怎么办

在当今全球化的时代&#xff0c;越来越多的企业和组织选择将业务拓展至海外市场。然而&#xff0c;随着业务的扩大和网络的延伸&#xff0c;也面临着来自不同地区的网络威胁和攻击风险。如果您的海外服务器遭受了DDOS攻击&#xff0c;以下是一些应对措施&#xff1a; 一、立即断…

【Redis】Redis的应用场景

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Redis ⛺️稳中求进&#xff0c;晒太阳 Redis的应用场景&#xff1a; 限流 要求10s内只能访问一次 RequestMapping("xian")public String xianLiu(String sign){String sign1 …

力扣刷题

文章目录 1. 双指针1.1 两数之和1.2 三数之和1.3 盛最多水的容器1.4 接雨水 2. 字串2.1 滑动窗口最大值 3. 动态规划4. 多维动态规划4.1 最长回文字串 1. 双指针 1.1 两数之和 思路&#xff1a;因为是有序数组&#xff0c; 1.2 三数之和 题目要求不能重复 思路&#xff1a;三…

简明固体物理--晶体的形成与晶体结构的描述

简明固体物理-国防科技大学 chapter 1 Formation of Crystal Contents and roadmapQuantum Mechanics and atomic structureElectronsOld quantum theoryMethod of Quantum MechanicsDistributing functions of micro-particles BindingCrystal structure and typical crystal…

YOLOv9(2):YOLOv9网络结构

1. 前言 本文仅以官方提供的yolov9.yaml来进行简要讲解。 讲解之前&#xff0c;还是要做一些简单的铺垫。 Slice层不做任何的操作&#xff0c;纯粹是做一个占位层。这样一来&#xff0c;在parse_model时&#xff0c;ch[n]可表示第n层的输出通道。 Detect和DDetect主要区别还…

Java开发从入门到精通(一):Java的基础语法进阶

Java大数据开发和安全开发 &#xff08;一&#xff09;Java注释符1.1 单行注释 //1.2 多行注释 /* */1.3 文档注释 /** */1.4 各种注释区别1.5 注释的特点1.5 注释的快捷键 &#xff08;二&#xff09;Java的字面量&#xff08;三&#xff09;Java的变量3.1 认识变量3.2 为什么…

例行性工作(at,crontab)

目录 单一执行的例行性工作at 语法 选项 时间格式 at的工作文件存放目录 at工作的日志文件 实例 命令总结&#xff1a; 循环执行的例行性工作crond 语法 选项 crontab工作调度对应的系统服务 crontab工作的日志文件 用户定义计划任务的文件所在目录 动态查看 crontab文件格式 文…

集合拆分Lists.partition的使用

集合拆分Lists.partition的使用 集合拆分Lists.partition的使用 需要的包 import com.google.common.collect.Lists;引入maven依赖 <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>21.0</…

真Unity-Editor二次开发-ScriptableObject 可自定义UI界面

关于ScriptablObject自定义 作为官方指定的&#xff0c;曾经我也吐槽过ScriptableObject很鸡肋&#xff0c;个人曾经也是强烈反对在项目中使用&#xff0c;但直到我今天看到下面这个代码&#xff0c;菜发现其实只是自己太菜鸡而已 --------------不想多写什么 -------------…

Rust组织管理,箱Crate包Package和模块module定义和区别,use关键字作用

Rust 组织管理 任何一门编程语言如果不能组织代码都是难以深入的&#xff0c;几乎没有一个软件产品是由一个源文件编译而成的。 本教程到目前为止所有的程序都是在一个文件中编写的&#xff0c;主要是为了方便学习 Rust 语言的语法和概念。 对于一个工程来讲&#xff0c;组织…

NineData与OceanBase完成产品兼容认证,共筑企业级数据库新生态

近日&#xff0c;云原生智能数据管理平台 NineData 和北京奥星贝斯科技有限公司的 OceanBase 数据库完成产品兼容互认证。经过严格的联合测试&#xff0c;双方软件完全相互兼容、功能完善、整体运行稳定且性能表现优异。 此次 NineData 与 OceanBase 完成产品兼容认证&#xf…