【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实现广播的例子
  • 🎄五、总结


在这里插入图片描述

🎄一、广播概述

在网络编程中,有三种常见的通信方式:单播、广播、多播(组播),这三种方式对比如下表:

类型IPv4IPv6TCPUDP所标识接口数递送到的接口数
单播支持支持支持支持一个一个
广播支持支持全体全体
多播可选支持支持一组整个组

广播的概念
广播是允许一台主机本地子网内所有主机 发送消息的一种通信方式。发送的广播分组会去往子网上的所有主机,包括发送者自身。

  • 广播只支持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、受限广播地址:{子网ID,-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》

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

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

相关文章

dolphinscheduler试用(一)(边用边修bug。。。。create tenant error)

&#xff08;作者&#xff1a;陈玓玏&#xff09; 前提&#xff1a;部署好了dolphinscheduler&#xff0c;部署篇见https://blog.csdn.net/weixin_39750084/article/details/136306890?spm1001.2014.3001.5501 官方文档见&#xff1a;https://dolphinscheduler.apache.org/zh…

常用“树”数据结构

哈夫曼树 在许多应用中&#xff0c;树中结点常常被赋予一个表示某种意义的数值&#xff0c;称为该结点的权。从树的根到任意结点的路径长度(经过的边数)与该结点上权值的乘积&#xff0c;称为该结点的带权路径长度。树中所有叶结点的带权路径长度之和称为该树的带权路径长度&am…

App原生开发:iOS和Android平台的比较(看这一篇就够了)

引言 移动应用的发展在过去几年里取得了巨大的突破&#xff0c;而原生开发作为构建高性能、富有交互性的应用程序的首选方法&#xff0c;一直占据着重要的地位。在这篇文章中&#xff0c;我们将探讨原生开发在两个主流移动平台——iOS和Android上的关键概念和技术。 概念和重…

关于制作Python游戏全过程(汇总1)

目录 前言: 1.plane_sprites模块: 1.1导入模块: 1.1.1pygame&#xff1a;一个用于创建游戏的Python库。 1.1.2random&#xff1a;Python标准库中的一个模块&#xff0c;用于生成随机数。 1.2定义事件代号: 1.2.1ENEMY_EVENT&#xff1a;自定义的敌机出场事件代号&#xf…

芯科科技为全球首批原生支持Matter-over-Thread的智能锁提供强大助力,推动Matter加速成为主流技术

智能锁领域的先锋企业U-tec和Nuki选择芯科科技解决方案&#xff0c;成为Matter-over-Thread应用的领先者 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&#xff08;亦称“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;今…

使用Fabric创建的canvas画布背景图片,自适应画布宽高

之前的文章写过vue2使用fabric实现简单画图demo&#xff0c;完成批阅功能&#xff1b;但是功能不完善&#xff0c;对于很大的图片就只能显示一部分出来&#xff0c;不符合我们的需求。这就需要改进&#xff0c;对我们设置的背景图进行自适应。 有问题的canvas画布背景 修改后的…

【排序】详解冒泡排序

一、思想 冒泡排序的基本思想是利用两两比较相邻记录的方式&#xff0c;通过一系列的比较和交换操作&#xff0c;使得较大或较小的元素逐渐移动到数列的一端。在每一轮的排序过程中&#xff0c;都会从数列的起始位置开始&#xff0c;对相邻的元素进行比较&#xff0c;如果它们…

基于SSM的洋洋线上服装商城系统的设计与实现

第1章 绪论 1.1 研究背景和意义 在如今这个信息时代&#xff0c;“网上购物”这种购物方式已经为越多的人认可。在此背景下&#xff0c;开发出稳定并且功能齐全的网络购物平台不可或缺&#xff0c;在这些需求的支持下&#xff0c;在先进的信息技术的支持下&#xff0c;产品销…

华为HQoS配置案例

HQoS基于层次化调度&#xff0c;cpe上支持三级队列&#xff1a; level3流队列&#xff1a;每个用户的同类业务是一个业务流&#xff0c;针对每个用户不同的业务流进行队列调度&#xff0c;流队列一般与业务类型对应&#xff08;EF、AF、BE等&#xff09;。 level2用户队列&…

Node.js 最佳实践:改善你的应用程序设计 | 开源日报 No.191

goldbergyoni/nodebestpractices Stars: 92.4k License: CC-BY-SA-4.0 Node.js Best Practices 是一个关于 Node.js 最佳实践的开源项目。该项目汇总了许多顶级内容&#xff0c;包括 80 多个最佳实践、样式指南和架构技巧。以下是该项目的核心优势和主要功能&#xff1a; 提供…

go并发模式之----使用时顺序模式

常见模式之二&#xff1a;使用时顺序模式 定义 顾名思义&#xff0c;起初goroutine不管是怎么个先后顺序&#xff0c;等到要使用的时候&#xff0c;需要按照一定的顺序来&#xff0c;也被称为未来使用模式 使用场景 每个goroutine函数都比较独立&#xff0c;不可通过参数循环…

docker pull 拉取失败,设置docker国内镜像

遇到的问题 最近在拉取nginx时&#xff0c;显示如下错误&#xff1a;Error response from daemon: Get “https://registry-1.docker.io/v2/”: net/http: request canceled (Client.Timeout exceeded while awaiting headers)。 这个的问题是拉取镜像超时&#xff0c;通过检索…

灯塔:CSS笔记(1)

CSS&#xff1a;层叠样式表 所谓层叠 即叠加的意思&#xff0c;表示样式可以一层一层的层叠覆盖 css写在style标签中&#xff0c;style标签一般写在head标签里面&#xff0c;title标签下面 <!DOCTYPE html> <html lang"en"> <head><meta cha…

Python Flask Web + PyQt 前后端分离的项目—学习成绩可视化分析系统

简介 使用工具&#xff1a; Python&#xff0c;PyQt &#xff0c;Flask &#xff0c;MySQL 注&#xff1a;制作重点在网页端&#xff0c;因此网页端的功能更全 WEB界面展示: 系统登录分为管理员&#xff0c;老师&#xff0c;学生3部分 管理员统一管理所有的账号信息以及登录…

DNS域名解析

DNS域名解析服务 1.DNS介绍 DNS 是域名系统 (Domain Name System) 的缩写&#xff0c;是因特网的一项核心服务&#xff0c;它作为可以将域名和IP地址相互映射的一个分布式数据库&#xff0c;能够使人更方便的访问互联网&#xff0c;而不用去记住能够被机器直接读取的IP数串。…

物联网与智慧城市:融合创新,塑造未来城市生活新图景

一、引言 在科技飞速发展的今天&#xff0c;物联网与智慧城市的融合创新已成为推动城市发展的重要力量。物联网技术通过连接万物&#xff0c;实现信息的智能感知、传输和处理&#xff0c;为智慧城市的构建提供了无限可能。智慧城市则运用物联网等先进技术&#xff0c;实现城市…

网络编程的学习

思维导图 多路复用代码练习 select完成TCP并发服务器 #include<myhead.h> #define SER_IP "192.168.125.73" //服务器IP #define SER_PORT 8888 //服务器端口号int main(int argc, const char *argv[]) {//1、创建用于监听的套接字int sfd -1;s…

[NSSCTF 2nd] web复现

1.php签到 <?phpfunction waf($filename){$black_list array("ph", "htaccess", "ini");$ext pathinfo($filename, PATHINFO_EXTENSION);foreach ($black_list as $value) {if (stristr($ext, $value)){return false;}}return true; }if(i…

python一张大图找小图的个数

python一张大图找小图的个数 一、背景 有时候我们在浏览网站时&#xff0c;发现都是前端搞出来的一张张图&#xff0c;我们只能用盯住屏幕的小眼睛看着&#xff0c;很累的统计&#xff0c;这个是我在项目中发现没办法统计&#xff0c;网上的教程很多&#xff0c;都不成功&…

【ELK日志分析系统】ELK+Filebeat分布式日志管理平台部署

ELKFilebeat部署一、ELK简介1、ELK组件1.1 其他组件 2、为什么要使用 ELK3、完整日志系统基本特征 二、ELK的工作原理三、ELK Elasticsearch 集群部署1、环境准备2、部署 Elasticsearch 软件(node节点)2.1 安装elasticsearch—rpm包2.2 修改elasticsearch主配置文件2.3 es性能调…