【Linux C | 网络编程】广播概念、UDP实现广播的C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍广播概念、UDP实现广播的C语言例子 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:2024-03-06 00:10:30
本文未经允许,不得转发!!!
目录
- 🎄一、广播概述
- 🎄二、广播地址
- 🎄三、UDP单播 和 UDP广播 的比较
- ✨3.1 UDP单播过程
- ✨3.2 UDP广播过程
- 🎄四、UDP实现广播的例子
- 🎄五、总结
🎄一、广播概述
在网络编程中,有三种常见的通信方式:单播、广播、多播(组播),这三种方式对比如下表:
类型 | IPv4 | IPv6 | TCP | UDP | 所标识接口数 | 递送到的接口数 |
---|---|---|---|---|---|---|
单播 | 支持 | 支持 | 支持 | 支持 | 一个 | 一个 |
广播 | 支持 | 支持 | 全体 | 全体 | ||
多播 | 可选 | 支持 | 支持 | 一组 | 整个组 |
广播的概念
广播是允许一台主机
向本地子网内所有主机
发送消息的一种通信方式。发送的广播分组会去往子网上的所有主机,包括发送者自身。
- 广播只支持IPv4,不支持IPv6:使用广播的IPv4应用程序一旦移植到IPv6,就必须使用多播重新编写;
- 广播支持UDP或原始IP,不支持TCP。
广播的用途
- 资源发现:知道子网中有我们想找的资源,但不知道其具体IP地址,可以往该子网中发一个广播,该资源主机收到广播后处理并回复,非资源主机不处理。举例:NVR发送广播搜索局域网内的IPC。
- 减少分组流通。
广播的缺点
子网内未参与相应广播的所有主机也会沿着协议栈向上完整地处理
收取的广播数据报,直到该数据报在UDP层处理时才被丢弃。
🎄二、广播地址
广播的实现需要往广播地址
发送广播分组。任何子网中最后一个IP地址就是广播地址。如果以{子网ID,主机ID}表示一个IP地址,则广播地址分为下面两种,-1表示所有位都位1:
- 1、子网定向广播地址:{子网ID,-1}。这是子网上所有接口的广播地址。举例来说,假设有一个 192.168.1/24 的子网,那么这个子网中最后一个IP就是 192.168.1.255/24 ,它就是该子网所有接口的
子网定向广播地址
。通常,路由器不转发目的地址为子网定向广播地址
的数据报。 - 2、受限广播地址:{-1,-1} 或
255.255.255.255
。路由器从不转发目的地址为255.255.255.255
的IP数据报。当应用程序设置了SO_BROADCAST
套接字选项,且发送目的地址为255.255.255.255
的UDP数据报时,大多数主机会将该目的地址转换成外出接口的子网定向广播地址
并发送到路由器。
255.255.255.255
用十六进制表示就是0xffffffff
。在Linux系统中,定义了一个宏INADDR_BROADCAST
来表示受限广播地址
,该宏定义在头文件<netinet/in.h>中,定义如下:/* Address to send to all hosts. */ #define INADDR_BROADCAST ((in_addr_t) 0xffffffff)
🎄三、UDP单播 和 UDP广播 的比较
✨3.1 UDP单播过程
下图说明了一个UDP数据报在单播情况下,怎样到达目的地的:
-
发送主机(图中最左边):
- ①进程在一个UDP套接字上调用sendto往IP地址192.168.42.3端口7433发送一个数据报;
- ②UDP层对它冠以一个UDP首部后把UDP数据报传递到IP层
- ③IP层对它冠以一个IPv4首部,确定其外出接口,在以太网情况下还激活ARP把目的IP地址映射成相应的以太网地址:
00:0a:95:79:bc:b4。 - ④该分组然后作为一个目的以太网地址为这个48位地址的以太网帧发送出去。该以太网帧的帧类型字段值为表示IPv4分组的
0x0800
。
-
目的主机(图中最右边):
- ①目的主机的以太网接口看到该帧后,比较并确定该帧的目的地址和自己以太网地址相同,于是读入该帧。由于帧类型是
0x0800
,该帧的分组被置于IP输入队列。 - ②IP层处理该分组会先比较该分组的目的地址,确定是本机IP地址之一才接受该分组,接着查看IPv4首部的协议字段,值为表示UDP的17,于是将该分组承载的数据报传递到UDP层。
- ③UDP层检查该数据报的目的端口,把该数据报置于相应套接字的接收队列,必要时会唤醒阻塞在该相应输入操作的进程,由进程读取这个新收取的数据报。
- ①目的主机的以太网接口看到该帧后,比较并确定该帧的目的地址和自己以太网地址相同,于是读入该帧。由于帧类型是
-
其他主机(图中中间):
- ①非目的主机的以太网口看到该帧后,比较该帧目的地址和自己以太网地址,比较结果不相同,于是忽略了这个帧。
✨3.2 UDP广播过程
下图说明了一个UDP数据报在广播情况下,怎样到达目的地的:
-
发送主机(图中最左边):
- ①进程在一个UDP套接字上调用sendto往IP地址192.168.42.255端口520发送一个数据报;
- ②UDP层对它冠以一个UDP首部后把UDP数据报传递到IP层;
- ③IP层对它冠以一个IPv4首部,确定其外出接口,因为目的地址是
子网定向广播地址
,所以映射为48位全为1的以太网地址:ff:ff:ff:ff:ff:ff
。 - ④该分组作为一个目的以太网地址为
ff:ff:ff:ff:ff:ff
的以太网帧发送出去,使得该子网的每个以太网接口(包括自身主机接口)都会接收到该帧。该以太网帧的帧类型字段值为表示IPv4分组的0x0800
。
-
子网内所有主机(包括自身主机):
- ①子网内的所有主机的以太网接口看到该帧后,因为目的地址是
ff:ff:ff:ff:ff:ff
,都会接收该帧。由于帧类型是0x0800
,该帧的分组传递到IP层。 - ②IP层确定该分组目的地址为广播地址后,会接受该分组,接着查看IPv4首部的协议字段,值为表示UDP的17,于是将该分组承载的数据报传递到UDP层。
- ③UDP层检查该数据报的目的端口,如果接收到该数据报的主机没有任何进程绑定值为520的UDP端口,则该主机的UDP代码会丢弃已收取的数据报,如图中中间主机。如果接收到该数据报的主机存在进程绑定了值为520的UDP端口,那么该进程把该数据报置于相应套接字的接收队列,必要时会唤醒阻塞在该相应输入操作的进程,由进程读取这个新收取的数据报。
- ①子网内的所有主机的以太网接口看到该帧后,因为目的地址是
🎄四、UDP实现广播的例子
下面给出一个使用UDP实现广播的例子,代码是之前文章的例子 入门知识:UDP协议、一个最简单的UDP客户端、一个最简单的UDP服务端 。
只需要在原本客户端修改两个地方就可以发送UDP广播数据报了:一个是在sendto
之前设置套接字选项SO_BROADCAST
;另一个是将sendto的目的地址设置为广播地址,这里使用INADDR_BROADCAST
。
发送UDP广播客户端步骤:
- 1、创建UDP套接字socket;
- 2、准备广播地址和端口;
- 3、设置广播套接字选项 SO_BROADCAST;
- 4、使用 sendto 发送广播数据报;
- 5、处理应答
- 6、关闭
UDP广播客户端代码也很简单,如下:
// brocastCli.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>#define USE_BRORDCAST 1int main()
{// 1、创建UDP套接字socketint sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd<0)perror("socket error" );// 2、准备广播地址和端口struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons (10086);
#if USE_BRORDCASTservaddr.sin_addr.s_addr = INADDR_BROADCAST;// 3、设置广播套接字选项 SO_BROADCASTint so_broadcast = 1;if(setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST,&so_broadcast,sizeof(so_broadcast)) < 0){perror("setsockopt");close(sockfd);return -1;}
#elseif (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0) // 设置本机IP为服务端IPperror("inet_pton error");
#endif// 4、使用 sendto 发送广播数据报if(sendto(sockfd, "Hello,I am udp client", strlen("Hello,I am udp client"), 0, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)perror("sendto error" );// 5、处理应答char recvline[256];int n = 0;struct sockaddr_in tmpAddr;bzero(&tmpAddr, sizeof(tmpAddr));socklen_t addrLen=sizeof(tmpAddr);while ( (n = recvfrom (sockfd, recvline, sizeof(recvline), 0, (struct sockaddr*)&tmpAddr, &addrLen)) > 0){recvline[n] = 0 ;/*null terminate */printf("recvfrom ip=[%s], [%s]\n",inet_ntoa(tmpAddr.sin_addr), recvline);bzero(&tmpAddr, sizeof(tmpAddr));}if (n < 0)perror("read error" );// 6、关闭close(sockfd);return 0;
}
UDP服务器不需要做任何改动,还是使用之前的例子,代码如下:
// brocastSer.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>int main()
{// 1、创建UDP套接字socketint sockfd = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd<0)perror("socket error" );// 2、准备服务端ip和端口struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons (10086);servaddr.sin_addr.s_addr = INADDR_ANY; // 指定ip地址为 INADDR_ANY,这样要是服务器主机有多个网络接口,服务器进程就可以在任一网络接口上接受客户端的连接// 3、绑定 bindif (bind(sockfd,(struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)perror("bind error" );// 4、使用 sendto、recvfrom 交互数据printf("UdpSer sockfd=%d, start \n",sockfd);char recvline[256];while(1){struct sockaddr_in cliaddr;bzero(&cliaddr, sizeof(cliaddr));socklen_t addrLen=sizeof(cliaddr);int n = recvfrom(sockfd, recvline, sizeof(recvline), 0, (struct sockaddr*)&cliaddr, &addrLen);if(n>0){recvline[n] = 0 ;/*null terminate */printf("recv sockfd=%d %d byte, [%s] addrLen=%d, cliIp=%s, cliPort=%d\n",sockfd, n, recvline, addrLen, inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);sendto(sockfd, "Hello,I am udp server", strlen("Hello,I am udp server"), 0, (struct sockaddr*)&cliaddr, addrLen);}}// 5、关闭close(sockfd);return 0;
}
分别在局域网内的几台机器运行UDP服务端brocastSer
,然后在其中一台机器运行广播客户端brocastCli
,下面是客户端的运行结果,收取到好几台运行着服务端主机对广播的响应:
🎄五、总结
👉本文介绍了广播的概念、广播的用途、广播的缺点、广播地址,对比了单播和广播的流程,最后给出了UDP实现广播的C语言例子。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
参考资料:
《Unix网络编程卷1》
相关文章:

【Linux C | 网络编程】广播概念、UDP实现广播的C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...

java 面向对象 day3
这里写目录标题 1、 内部类1.1 成员内部类 静态内部类1.2 局部内部类1.3 匿名内部类[重点] 2、枚举2.1 使用枚举类 设计单例模式2.2 小实例 3、泛型3.1 认识泛型3.2 泛型类3.3 泛型接口3.4 泛型方法3.5 注意事项 1、 内部类 内部类 就是定义在一个类中的类 1.1 成员内部类 静…...
Flink 大数据 学习详情
参考视频: 尚硅谷大数据Flink1.17实战教程从入门到精通_哔哩哔哩_bilibili 核心目标: 数据流上的有状态的计算 具体说明: Apache Flink是一个 框架 和 分布式处理引擎,用于对 无界(eg:kafka) 和…...

[项目设计] 从零实现的高并发内存池(四)
🌈 博客个人主页:Chris在Coding 🎥 本文所属专栏:[高并发内存池] ❤️ 前置学习专栏:[Linux学习] ⏰ 我们仍在旅途 目录 6.内存回收 6.1 ThreadCache回收内存 6.2 CentralCache回收内存 Rele…...
02.URL的基本知识和使用
一.认识 URL 1. 为什么要认识 URL ? 虽然是后端给我的一个地址,但是哪部分标记的是服务器电脑,哪部分标记的是资源呢?所以为了和服务器有效沟通我们要认识一下 2. 什么是 URL ? 统一资源定位符,简称网址ÿ…...

人工智能指数报告2023
人工智能指数报告2023 主要要点第 1 章 研究与开发第 2 章 技术性能第 3 章 人工智能技术伦理第 4 章 经济第 5 章 教育第 6 章 政策与治理第 7 章 多样性第 8 章 舆论 人工智能指数是斯坦福大学以人为本的人工智能研究所(HAI)的一项独立倡议,…...
Android如何对应用进行系统签名
一、使用命令 获取签名文件 从系统源码环境中获取签名相关文件: platform.x509.pem、platform.pk8 、signapk.jar platform.x509.pem、platform.pk8 位于 ../build/target/product/security 目录下。signapk.jar 位于 ../out/host/linux-x86/framework 目录下。 …...

【系统安全加固】Centos 设置禁用密码并打开密钥登录
文章目录 一,概述二,操作步骤1. 服务器端生成密钥2. 在服务器上安装公钥3.下载私钥到本地(重要,否则后面无法登录)4. 修改配置文件,禁用密码并打开密钥登录5. 重启sshd服务6. 配置xshell使用密钥登录 一&am…...
关于我在项目中封装的一些自定义指令
什么是指令 在Vue中提供了一套为数据驱动视图更为方便的操作,这些操作被称为指令系统。我们看到的v-来头的行内属性,都是指令,不同的指令可以完成或者实现不同的功能。 除了核心功能默认内置的指令(v-model和v-show)…...
react经验11:访问循环渲染的子组件内容
前有访问单个子组件的需求,现在进一步需要访问循环渲染中的子组件。 访问单个子组件的成员 实施步骤 子组件//child.tsx export declare type ChildInstance{childMethod:()>void } const Child(props:{value:stringonMounted?:(ref:ChildInstance)>void …...
Java开发工程师面试题(业务功能)
一、订单超时未支付自动关闭的几种实现方式。 定时任务扫描:在订单创建时,为订单创建一个定时任务,并设置一个超时时间。后端服务器会定期检查任务的创建时间是否超过了超时时间。如果是,则将订单设置为关闭状态。这种方案需要后…...

BUUCTF-Misc-百里挑一
题目链接:BUUCTF在线评测 (buuoj.cn) 下载附件打开是一个流量包文件: 全是在传图片时候的流量,先把图片保存出来文件–>导出对象–>HTTP–>保存到一个文件夹 然后使用kali下的exiftool找到了一半flag exiftool *|grep flag 另外一半…...
【力扣刷题练习】42. 接雨水
题目描述: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。 题目解答: class Solution {public int trap(int[] height) {int n height.length;int ans 0;if (n < 3)return…...

鸿蒙实战开发:数据交互【RPC连接】
概述 本示例展示了同一设备中前后台的数据交互,用户前台选择相应的商品与数目,后台计算出结果,回传给前台展示。 样例展示 基础信息 RPC连接 介绍 本示例使用[ohos.rpc]相关接口,实现了一个前台选择商品和数目,后台…...

QLC SSD:LDPC纠错算法的优化方案
随着NAND TLC和QLC出现,LDPC也在不断的优化研究,提升纠错能力。小编看到有一篇来自Microchip发布的比较详细的LDPC研究数据,根据自己的理解分析解读给大家,如有错误,请留言指正! 文档中测试LDPC(Low-Density Parity-Check)码是为了评估其在不同配置下对数据错误的有效…...

【Flutter 面试题】main()和runApp()函数在Flutter的作用分别是什么?有什么关系吗?
【Flutter 面试题】main()和runApp()函数在Flutter的作用分别是什么?有什么关系吗? 文章目录 写在前面解答补充说明 写在前面 关于我 ,小雨青年 👉 CSDN博客专家,GitChat专栏作者,阿里云社区专家博主&…...

ChatGPT高效提问——说明提示技巧
ChatGPT高效提问——说明提示技巧 现在,让我们开始体验“说明提示技巧”(IPT, Instructions Prompt Technique)和如何用它生成来自ChatGPT的高质量的文本。说明提示技巧是一个通过向ChatGPT提供需要依据的具体的模型的说明来指导ChatGPT输出…...
从零学算法41
41.给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 输入:nums [1,2,0] 输出:3 示例 2: 输入:nums […...

FPGA高端项目:FPGA基于GS2971的SDI视频接收+OSD动态字符叠加,提供1套工程源码和技术支持
目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收转HDMI输出应用本方案的SDI接收图像缩放应用本方案的SDI接收纯verilog图像缩放纯verilog多路视频拼接应用本方案的SDI接收HLS图像缩放HLS多路视频拼接应用本方案的SDI接收HLS多路视频融合叠加应用…...

UML-类图详解
UML中基本概念说明 UML类图中关系连接线说明 UML类图说明 号表示public、-表示表示private、#表示protected UML类关系详解 泛化(Generalization)关系 简单的讲就是类之间的继承关系。在UML中,泛化关系用空心三角形实线来表示&…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...