网络编程探索系列之——广播原理剖析
hello !大家好呀!
欢迎大家来到我的网络编程系列之广播原理剖析,在这篇文章中,
你将会学习到如何在网络编程中利用广播来与局域网内加入某个特定广播组的主机!
希望这篇文章能对你有所帮助
,大家要是觉得我写的不错的话,那就点点免费的小爱心吧
!
![]()
目录
一.什么是广播?
1.1 广播的概念
1.2 广播通信原理
二 .如何实现广播通信
2.1 广播的IP地址
IPv4
IPv6
特殊用途的广播地址
2.2 实现步骤
2.3 网卡接口信息
三.广播代码实例
一.什么是广播?
1.1 广播的概念
广播是一种网络通信技术,允许数据包(如 IP 数据包)被发送到网络上的所有设备。在广播通信中,数据包不是发送给特定的接收者,而是发送给网络中的所有设备。每个设备都会接收到这个数据包,但只有特定地址的设备会响应。广播通常用于局域网(LAN)中,允许设备之间直接通信,而不需要通过路由器。这种通信方式可以提高网络的效率,因为它避免了数据包在网络中的不必要的转发。
1.2 广播通信原理
广播通信的工作原理如下:
-
发送方:发送方将数据包发送到广播地址。在 IP 网络中,广播地址是一个特殊的 IP 地址,通常是 255.255.255.255。
-
网络设备:网络中的每个设备都会接收到这个广播数据包。每个设备都会检查数据包的目的地 IP 地址,以确定是否应该响应。
-
响应:如果数据包的目的地 IP 地址与设备自己的 IP 地址匹配,或者设备被配置为响应广播数据包,那么该设备将发送一个响应数据包。
-
接收方:发送方(或广播请求的发起方)会接收到来自响应设备的响应数据包。
广播通信通常用于以下场景:
- DHCP 服务器:在局域网中,DHCP 服务器使用广播来发现并分配 IP 地址给新加入网络的设备。
- 网络管理:网络管理员可以使用广播来诊断网络问题或发送通知给网络中的所有设备。
- 组播:虽然组播(multicast)与广播类似,但它允许数据包发送给一组特定的接收者,而不是所有设备。组播通常用于多媒体流等应用。
在实际网络环境中,广播通信可能会受到一些限制,例如防火墙规则或网络设备的配置。此外,由于广播通信可能会导致网络拥塞,一些网络设备可能会限制或阻止广播流量。
二 .如何实现广播通信
2.1 广播的IP地址
在 IP 网络中,广播地址用于将数据包发送到网络上的所有设备。广播地址可以是 IP 地址的一部分,具体取决于网络的地址类型和配置。以下是不同 IP 地址类型中的广播地址:
IPv4
在 IPv4 网络中,广播地址通常与子网掩码有关。广播地址可以通过将子网掩码中的所有主机位设置为 1 来计算。例如,如果你有一个子网掩码 255.255.255.0,那么对于地址 192.168.1.10,其广播地址将是 192.168.1.255。
IPv6
在 IPv6 网络中,广播地址的格式是 ff00::/8。这个地址范围是专门用于广播和多播的。然而,与 IPv4 不同,IPv6 网络中通常不使用广播地址来与网络中的所有设备通信。相反,IPv6 使用多播地址,如 ff02::1,来代替广播地址。
特殊用途的广播地址
除了上述通用广播地址外,还有一些特殊用途的广播地址:
224.0.0.0/4:这是一个特殊的多播地址范围,用于多播组播。255.255.255.255:这是一个用于直接连接的广播地址,通常在同一网络段内使用。
广播地址的目的是将数据包发送到网络中的所有设备。在实际应用中,广播地址的用法和实现可能会因网络配置和协议的不同而有所差异。在 IPv4 网络中,广播地址通常与子网掩码有关;而在 IPv6 网络中,广播地址的用法相对较少,多播地址更为常见。
例如:我在centos系统上查看我的网卡信息:

我的ens33网卡ip地址为192.168.80.132 那么我的该接口的广播地址为192.168.80.255
2.2 实现步骤
当我们了解了广播的ip地址后,我们就可以着手与广播的编程实现了,在编程中实现广播通信通常涉及使用特定的网络编程接口,如 UDP 套接字。以下是一个基本的步骤,用于在 C 语言中实现广播编程:
-
创建套接字: 使用
socket函数创建一个 UDP 套接字。你需要指定协议族(如 AF_INET)和协议类型(如 SOCK_DGRAM)。 -
设置套接字选项: 你可能需要设置套接字选项,如
SO_BROADCAST,以允许广播通信。 -
绑定套接字: 使用
bind函数将套接字绑定到一个地址和端口。这个地址通常是广播地址,端口是你选择的用于广播通信的端口。 -
发送广播消息: 使用
sendto函数发送广播消息。你需要指定广播地址和端口,以及消息内容。 -
接收广播消息: 如果服务器端需要接收广播消息,可以使用
recvfrom函数来接收来自广播地址的消息。 -
关闭套接字: 完成通信后,使用
close函数关闭套接字
这是一般步骤,其中我们还需要更加多的细节和基础知识,大家可以去看我前面博客哦,这里给出相关链接:[C++/Linux] UDP编程-CSDN博客 , [C++/Linux] socket套接字函数-CSDN博客
2.3 网卡接口信息
同时,对于客户端代码来说,我们需要获取某个网卡接口的信息,以便我们得到其多播地址,那就要涉及到struct ifreq , 这个结构通常用于获取和设置网络接口的参数:
struct ifreq {char ifr_name[IFNAMSIZ]; /* Interface name */union {struct sockaddr ifr_addr;struct sockaddr ifr_dstaddr;struct sockaddr ifr_broadaddr;struct sockaddr ifr_netmask;struct sockaddr ifr_hwaddr;};short ifr_flags; /* Flags */int ifr_ifindex; /* Interface index */int ifr_metric; /* Metric */int ifr_mtu; /* MTU */// 可能还有其他字段...
};
这个结构中的字段包括:
ifr_name: 网络接口的名称,例如 “eth0” 或 “wlan0”。ifr_addr等字段: 网络接口的地址信息,包括 IP 地址、子网掩码、广播地址等。ifr_flags: 接口的标志,如IFF_UP(接口已启动)、IFF_RUNNING(接口正在运行)等。ifr_ifindex: 网络接口的索引。ifr_metric: 接口的度量值,用于路由选择。ifr_mtu: 接口的最大传输单元。
要使用 struct ifreq,你通常会创建一个实例,设置适当的字段,然后通过 ioctl 调用来获取或设置网络接口的属性。例如,获取指定接口的 IP 地址,你可以这样做:
int sockfd;
struct ifreq ifr;
sockfd = socket(AF_INET, SOCK_DGRAM, 0);// 复制接口名称到ifr_name
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);// 使用SIOCGIFADDR ioctl命令获取接口地址
if (ioctl(sockfd, SIOCGIFADDR, &ifr) == -1) {perror("ioctl");return 1;
}// 现在ifr.ifr_addr包含IP地址
printf("IP Address: %s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));close(sockfd);
这段代码打开了一个数据报套接字,将接口名称设置为 “eth0”,然后使用 ioctl 获取该接口的 IP 地址,并将其打印出来。
三.广播代码实例
在这个例子中,服务器在局域网上侦听,当有数据到来的时候,判断udp数据报中是否含有关键字 IP_FOUND,如果有,说明此为某客户端的广播通讯消息,服务器会回应含IP_FOUND_ACK关键字的消息给客户端,如果客户端收到这条消息,就会判断该局域网上目前存在服务器,同时可以在消息里说明服务器的ip地址,这样客户端更能了解到当前局域网上的服务器信息,由于是UDP数据报,我们使用sendto发送数据,recvfrom接收消息。
服务器代码:
#include<t_stdio.h>
#include<t_file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <sys/select.h>
#include<stdlib.h>
#include <arpa/inet.h>
#include<signal.h>
#define DBGPRINT printfvoid sig_process(int signo){//信号处理函数printf("catch a exit signal..\n");_exit(0);
}int main(int argc ,char * argv[]){int ret = -1;int sock = -1;int count;socklen_t from_len;struct sockaddr_in local_addr ; //本地地址struct sockaddr_in client_addr ; //客户端地址fd_set readfd ; //文件描述符集合,用于接收客户端请求char buffer[32];//设置数据数组,用于数据接收发送struct timeval timeout ;//超时设置timeout.tv_sec = 2;timeout.tv_usec = 0;signal(SIGINT,sig_process);//添加sigint信号到信号掩码//创建数据报套接字sock = socket(AF_INET , SOCK_DGRAM , 0);if(sock < 0) E_MSG("socket",-1);//本地地址数据清零//memset((void *)local_addr, 0 , sizeof(struct sockaddr_in));//设置本地地址数据local_addr.sin_family = AF_INET;local_addr.sin_addr.s_addr = htonl(INADDR_ANY);//本地地址local_addr.sin_port = htons(8888); //用8888端口进行监听//本地绑定ret = bind(sock , (struct sockaddr *)&local_addr, sizeof(local_addr));if(ret!=0)E_MSG("bind",-1);//主处理过程while(1){//先将文件描述符清零FD_ZERO(&readfd);//将套接字文件描述符加入读集合FD_SET(sock,&readfd);//监听是否有数据到来ret = select(sock+1 , &readfd , NULL,NULL,&timeout);printf("ret is : %d/n" , ret);switch (ret){case -1 ://发生错误,break;case 0 :// 超时break;default: //有数据到来if(FD_ISSET(sock , &readfd)){//接收数据from_len = sizeof(client_addr); // 初始化from_lencount = recvfrom(sock , buffer , 32 , 0 ,(struct sockaddr *) & client_addr, from_len);DBGPRINT("recv msg is %s\n", buffer);//打印接收的信息if(strstr(buffer , "IP_FOUND")){//查看是否为ip广播请求数据报//将应答数据复制进去memcpy(buffer , "IP_FOUND_ACK" , strlen("IP_FOUND_ACK")+1);//发送应答数据count = sendto(sock , buffer , strlen(buffer) , 0 ,(struct sockaddr *)&client_addr,from_len);}}}}return 0;
}
客户端代码:
#include<t_stdio.h>
#include<t_file.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <sys/select.h>
#include<stdlib.h>
#include <arpa/inet.h>
#include<signal.h>
#include<net/if.h>
#include <sys/ioctl.h>
#define DBGPRINT printfvoid sig_process(int signo){//信号处理函数printf("catch a exit signal..\n");_exit(0);
}int main(int argc ,char * argv[]){int ret = -1 , sock = -1 , so_broadcast = 1, from_len = 0, count = 0;struct ifreq ifr;struct sockaddr_in broadcast_addr ; //本地广播地址struct sockaddr_in server_addr ; //服务器地址fd_set readfd ; //设置接收信息合集,和服务器代码一样char buffer[32];//设置数据数组,用于数据接收发送struct timeval timeout ;//超时设置timeout.tv_sec = 2;timeout.tv_usec = 0;signal(SIGINT,sig_process);//添加sigint信号到信号掩码sock = socket(AF_INET , SOCK_DGRAM , 0); //创建UDP数据报套接字if(sock < 0 ) E_MSG("socket" , -1);//将需要使用的网络接口字符串复制到网卡结构中strcpy(ifr.ifr_name , "ens33");//获取广播地址if(ioctl(sock,SIOCGIFBRDADDR, &ifr ) == -1){E_MSG("ioctl",-1);}//将获得的广播地址给本地广播地址结构memcpy(&broadcast_addr , &ifr.ifr_broadaddr , sizeof(struct sockaddr_in));//设置广播端口broadcast_addr.sin_port = htons(8888) ; //设置广播端口//设置套接字可以进行广播操作ret = setsockopt(sock , SOL_SOCKET , SO_BROADCAST , &so_broadcast ,sizeof(so_broadcast));//开始发送广播信息int times = 10 , i = 0 ;for(i = 0 ; i < times ; i++){//广播发送服务器地址请求ret = sendto(sock , "IP_FOUND" , strlen("IP_FOUND") , 0 ,(struct sockaddr * ) &broadcast_addr , sizeof(broadcast_addr));if(ret == -1)continue ; //发送失败就继续下一次发送//先将文件描述符清零FD_ZERO(&readfd);//将套接字文件描述符加入读集合FD_SET(sock,&readfd);//监听是否有数据到来ret = select(sock+1 , &readfd , NULL,NULL,&timeout); //这里和服务器代码一样switch (ret){case -1://发生错误break;case 0 ://超时break;default://成功监听到服务器回应if(FD_ISSET(sock , &readfd)){count = recvfrom(sock , buffer , 32 , 0 ,(struct sockaddr *)&server_addr , &from_len );DBGPRINT("recv msg is %s\n" , buffer);//判断是否为广播回应消息if(strstr(buffer , "IP_FOUND_ACK")){printf("found server IP is %s\n", inet_ntoa(server_addr.sin_addr));//打印服务器ip地址}break;}}}return 0;
}
好啦!到这里这篇文章就结束啦,关于实例代码中我写了很多注释,如果大家还有不懂得,可以评论区或者私信我都可以哦
!! 感谢大家的阅读,我还会持续创造网络编程相关内容的,记得点点小爱心和关注哟!![]()
相关文章:
网络编程探索系列之——广播原理剖析
hello !大家好呀! 欢迎大家来到我的网络编程系列之广播原理剖析,在这篇文章中, 你将会学习到如何在网络编程中利用广播来与局域网内加入某个特定广播组的主机! 希望这篇文章能对你有所帮助,大家要是觉得我写…...
jar包解压和重新打包
1、Windows系统上解压和重新打包jar包的命令: (1). 解压jar包: jar -xf yourJarFile.jar (2). 重新打包jar包: jar -cf newJarFile.jar * 2、Linux系统上解压和重新打包jar包的命令: (1). 解压jar包: unzip your…...
Python基于Django的微博热搜、微博舆论可视化系统
博主介绍:✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇dz…...
Flink SQL:debezium-json 格式的表一定是数据库的 CDC 数据吗?
debezium-json 格式有一种非常典型的应用场景,就是:上游(Source)是一张使用 Flink CDC 接入的关系数据库中的表,下游(Sink)是一张创建在 Kafka 上的表,这张表的 format 往往会定义为 debezium-json,以便 Flink 能获得全面的 CDC 信息用于流上的实时处理,这种场景我们…...
基于STM32的RFID智能门锁系统
本文针对RFID技术,着重研究了基于单片机的智能门锁系统设计。首先,通过链接4*4按键模块与主控STM32,实现了多种模式,包括刷卡开锁、卡号权限管理、密码开锁、修改密码、显示实时时间等功能。其次,采用RC522模块与主控S…...
测试用例的编写评审
1、什么叫软件测试用例 什么是测试用例 测试用例(TestCase) 是为项目需求而编制的一组测试输入、执行条件 以及预期结果,以便测试某个程序是否满足客户需求。–测试依据 可以总结为:每一个测试点的数据设计和步骤设计。–测试用例 2、测试用例的重要性(了解) 2.1…...
二叉树的前、中、后序遍历【c++】
前序遍历:根左右 中序遍历:左根右 后序遍历:左右根 #include <iostream> #include <vector> using namespace std;//双链表节点结构 typedef struct treeNode {int value;struct treeNode* left;struct treeNode* right;treeNod…...
Hadoop HDFS:海量数据的存储解决方案
引言 在大数据时代,数据的存储与处理成为了业界面临的一大挑战。Hadoop的分布式文件系统(Hadoop Distributed File System,简称HDFS)作为一个高可靠性、高扩展性的文件系统,提供了处理海量数据的有效解决方案。本文将…...
Leetcode二十三题:合并K个升序链表【22/1000 python】
“合并K个升序链表”,这是一道中等难度的题目,经常出现在编程面试中。以下是该问题的详细描述、解题步骤、不同算法的比较、代码示例及其分析。 问题描述 给你一个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中…...
03-echarts如何画立体柱状图
echarts如何画立体柱状图 一、创建盒子1、创建盒子2、初始化盒子(先绘制一个基本的二维柱状图的样式)1、创建一个初始化图表的方法2、在mounted中调用这个方法3、在方法中写options和绘制图形 二、画图前知识1、坐标2、柱状图图解分析 三、构建方法1、创…...
2024蓝桥A组E题
成绩统计 问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序难度等级 问题描述 题目有问题方差定义那加平方(vi-v) 格式输入 输入的第一行包含三个正整数n,k,T ,相邻整数之间使用一个空格分隔。 第二行包含n个正整数…...
Java单例模式
单例模式 什么是单例模式介绍实现单例模式的几种实现方式1. 懒汉式,线程不安全2、懒汉式,线程安全3、饿汉式4、双检锁/双重校验锁(DCL,即 double-checked locking)5、登记式/静态内部类6、枚举 什么是单例模式 单例模…...
04—常用方法和正则表达式
一、字符串 1.length 属性返回字符串的长度(字符数)。 2.在字符串中查找字符串 indexOf() 字符串使用 indexOf() 来定位字符串中某一个指定的字符首次出现的位置 如果没找到对应的字符函数返回-1 lastIndexOf() 方法在字符串末尾开始查找字符串出现的位置。 3.replace() 方…...
Python异常处理机制详解及示例
Python异常处理机制详解及示例 在编程过程中,异常处理是一项至关重要的技能。Python作为一种功能强大的编程语言,提供了一套完善的异常处理机制,使得程序在遇到错误或异常情况时能够优雅地处理,而不是直接崩溃。本文将详细介绍Py…...
解决:Java后端返回给前端的Date格式数据相差8小时的问题
问题描述: 后端得到的数据是对的,但是返回给前端后,数据比原数据慢了8小时。 原因: json数据在返回浏览器端是会被spring-boot默认的Jackson框架转换,而Jackson框架默认的时区GMT(相对于中国是少了8小时…...
linux安装weblogic
版本 Linux: Red Hat Enterprise Linux Server 6.9 64bit(安装了图形界面) JDK: 1.8U361 64bit weblogic: fmw_14.1.1.0.0_wls.jar 安装手顺 安装配置JDK 下载jdk压缩包 下载取得jdk-8I361-linux-x64.tar.gz将压缩包放置到linux,并解压缩到指定目录tar xvf jdk-8u201-…...
Unity WebGL Release-Notes
🌈WebGL Release-Notes 收集的最近几年 Unity各个版本中 WebGL的更新内容 💡WebGL Release-Notes 2023 💡WebGL Release-Notes 2022 💡WebGL Release-Notes 2021 💡WebGL Release-Notes 2020...
Excel 记录单 快速录入数据
一. 调出记录单 ⏹记录单功能默认是隐藏的,通过如下如图所示的方式,将记录单功能显示出来。 二. 录入数据 ⏹先在表格中录入一行数据,给记录单一个参考 ⏹将光标至于表格右上角,然后点击记录单按钮,调出记录单 然后点…...
go 利用channel实现定时任务
package mainimport ("fmt""net/http""time" )func main() {// 创建一个定时器,每隔1秒钟执行一次ticker : time.NewTicker(1 * time.Second)done : make(chan bool)//设置3s超时,避免请求时间过长client : http.Client{T…...
JWT介绍
JWT JSON Web Token (JWT) 是一种开放标准 (RFC 7519),提供一种简洁且自包含的方式,以JSON形式在通信双方间传递信息。这些信息可通过数字签名进行验证,确保其可信度。JWT 可以使用密钥(HMAC)或 RSA 或 ECDSA 的公钥/…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
