网络编程 | UDP广播通信

server/2025/1/19 12:22:42/

1、什么是广播

        在上一篇博客文章中已经对UDP进行了详细的说明介绍及如何编程实现。本文将接着上一文的内容,在其基础上,对UDP的知识体系进一步深入的讲解。

        网络编程 | UDP套接字通信及编程实现经验教程-CSDN博客

        例子:在一些中小学的操场中,通常会安装大功率喇叭用于播放广播体操音乐和上下课铃声,现在操场内有若干学生,当铃声响起时,学生们根据听到的指令开始做体操动作。

        这个场景可以用来解释网络通信中的“广播”概念。但如果操场内只有一个学生,那么虽然广播内容(如铃声或指令)仅由这一个学生接收,这个情况被称为单播,但在技术定义上,这种情况仍然被视为广播因为广播的本质在于信息的发送方式——即信息被发送到特定范围内的所有潜在接收者,而不论实际接收者的数量如何。在上面的这个例子中,“操场”代表了广播地址范围,喇叭作为广播的发送端,而位于操场内的学生则为广播的接收端。

  • 单播是指数据包被发送给单一的接收方,即每次通信只针对一个目标。
  • 广播则是指将信息同时发送给特定范围(如局域网)内的所有主机。即使该范围内实际上只有一个接收者,只要发送方式是面向所有可能接收者的,它就属于广播的形式。

        因此,在上述操场的例子中,无论当前有多少学生在场,喇叭播放的铃声都是以广播形式发送出去的,区别只在于实际接收到广播的人数不同而已。这一过程与计算机网络中使用UDP协议进行广播通信的原理相似,其中信息被发送到指定的网络段,可供该段内的所有设备接收。

2、广播的特点

        只有用户数据报套接字(使用UDP协议)才能广播。UDP(用户数据报协议)广播是一种网络通信方式,它允许信息在同一局域网内的所有设备之间共享。

①、高效性:广播消息只需发送一次,即可被局域网内的所有设备接收到,这使得在需要通知多个接收者时非常高效。

②、无连接的传输:UDP本身是无连接的协议,这意味着在发送广播消息之前不需要建立与接收方的连接。因此,它可以快速地发送数据,但不保证数据能够成功到达或按顺序到达。

③、不可靠的数据传输:由于UDP不提供确认机制、重传机制或流量控制,所以它不能保证消息一定会被接收方收到。如果可靠性是关键需求,则可能需要额外的上层协议来确保消息的成功传输。

④、有限的作用范围:UDP广播通常限制在本地子网内,即只能在同一局域网中的设备之间进行传播。这是因为路由器默认情况下不会转发广播消息到其他网络,以避免不必要的网络流量和潜在的安全问题。

⑤、使用特殊的目的地址:在IPv4中,广播地址通常是子网中主机部分全为1的地址(例如,在子网192.168.1.0/24中,广播地址为192.168.1.255)。而IPv6不支持传统的广播概念,取而代之的是多播。

⑥、适合特定场景:UDP广播非常适合于那些需要向网络上的所有设备发送少量信息的应用程序,如网络发现服务、动态主机配置协议(DHCP)等。

⑦、安全考虑:因为任何设备都可以监听并响应广播消息,所以在设计使用广播的应用程序时,需要考虑到潜在的安全风险,比如防止未经授权的访问或攻击。

        以192.168.1.0网段为例:***.***.***.255 代表该网段的广播地址。发送给该地址的数据包,可被网段内的所有主机接收。

        比如博主当前PC所处的局域网段 是 192.168.1.0 ,那么广播地址就是 192.168.1.255

sendto("你好", 192.168.1.255);

3、广播通信流程

        因广播是基于UDP实现的,故广播的发送端和接收端的实现流程,与常见的UDP的客户端与服务器的流程大致相同。

4、广播通信的程序

(1)、广播发送端

①、创建数据报套接字

int socketfd = socket(AF_INET, SOCK_DGRAM, 0);

②、设置socketfd套接字文件描述符的属性为广播 。(也就是允许发送广播数据包)

        SO_BROADCAST -----> 使用广播方式传送

int broadcast_flag = 1;
setsockopt(sockfd , SOL_SOCKET, SO_BROADCAST, &broadcast_flag, sizeof(broadcast_flag));

③、发送数据 ,指定接收方为广播地址

struct sockaddr_in sendAddr;
sendAddr.sin_family = AF_INET;
sendAddr.sin_port = htons(10000);
sendAddr.sin_addr.s_addr = inet_addr("192.168.1.255");//一定是广播地址,广播发送
sendto(sockfd,buf, strlen(buf), 0, (struct sockaddr*)&sendAddr, sizeof(sendAddr));

④、关闭套接字

close(socketfd);

(2)、广播接收端

①、创建用户数据报套接字

int socketfd = socket(AF_INET, SOCK_DGRAM, 0);

②、绑定(192.168.1.255)广播IP地址和端口号 (10000)

        注意:绑定的端口必须和发送方指定的端口相同

struct sockaddr_in ownAddr;
ownAddr.sin_family = AF_INET;
ownAddr.sin_port = htons(10000);
//uint32_t htonl(uint32_t hostlong);  将 主机IP转为 网络IP
ownAddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY(0.0.0.0) 代表本机所有的地址  //inet_addr("192.168.1.255");

③、接收数据

recvfrom(socketfd, ...);

④、关闭套接字

close(socketfd);

(3)、广播实现程序

①、广播发送端
#include<stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>int main(int argc, char **argv)
{printf("广播发送端(UDP协议)...............\n");//1、创建数据报套接字int socketfd = socket(AF_INET, SOCK_DGRAM, 0);if(socketfd == -1){perror("socket error");return -1;}//2、设置套接字文件描述符socketfd的属性为广播(也就是允许发送广播数据包) int broadcast_flag=1;setsockopt(socketfd,SOL_SOCKET, SO_BROADCAST, &broadcast_flag, sizeof(broadcast_flag));//3、发送数据,并且指定接收方为广播地址struct sockaddr_in sendAddr;//IPV4地址结构体变量sendAddr.sin_family = AF_INET;sendAddr.sin_port = htons(10000);sendAddr.sin_addr.s_addr = inet_addr("192.168.1.255");//一定是广播地址,广播发送while(1){char buf[1024]={0};printf("data:");scanf("%s",buf);sendto(socketfd,buf, strlen(buf), 0, (struct sockaddr *)&sendAddr, sizeof(sendAddr));}close(socketfd);return 0;    
}
②、广播接收端
#include<stdio.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>int main(int argc, char **argv)
{printf("广播接收端(UDP协议)...............\n");//1、创建数据报套接字int socketfd = socket(AF_INET, SOCK_DGRAM, 0);if(socketfd == -1){perror("socket error");return -1;}//2、绑定(192.168.1.255)广播IP地址和端口号 (10000)struct sockaddr_in ownAddr;ownAddr.sin_family = AF_INET;ownAddr.sin_port = htons(10000); //s unsigned short int     ownAddr.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY(0.0.0.0) 代表本机所有的地址  //inet_addr("192.168.1.255");bind(socketfd, (struct sockaddr *)&ownAddr, sizeof(ownAddr));struct sockaddr_in otherAddr;int len = sizeof(struct sockaddr_in);while(1){char buf[1024]={0};recvfrom(socketfd, buf, sizeof(buf), 0, (struct sockaddr *)&otherAddr, &len);printf("来自 %s:%u  recv:%s\n",inet_ntoa(otherAddr.sin_addr),ntohs(otherAddr.sin_port),buf);}close(socketfd);return 0;    
}

http://www.ppmy.cn/server/159623.html

相关文章

【Linux】线程全解:概念、操作、互斥与同步机制、线程池实现

&#x1f3ac; 个人主页&#xff1a;谁在夜里看海. &#x1f4d6; 个人专栏&#xff1a;《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长&#xff0c;行则将至 目录 &#x1f4da;一、线程概念 &#x1f4d6; 回顾进程 &#x1f4d6; 引入线程 &#x1f4d6; 总结 &a…

牛客---mysql

查找学校是北大的学生信息_牛客题霸_牛客网 题目&#xff1a;现在运营想要筛选出所有北京大学的学生进行用户调研&#xff0c;请你从用户信息表中取出满足条件的数据&#xff0c;结果返回设备id和学校。 示例&#xff1a;user_profile iddevice_idgenderageuniversityprovinc…

精选了几道MySQL的大厂面试题,被提问的几率很高!

&#x1f3a5; 作者简介&#xff1a; CSDN\阿里云\腾讯云\华为云开发社区优质创作者&#xff0c;专注分享大数据、Python、数据库、人工智能等领域的优质内容 &#x1f338;个人主页&#xff1a; 长风清留杨的博客 &#x1f343;形式准则&#xff1a; 无论成就大小&#xff0c;…

vue 学习笔记 - 创建第一个项目 idea

1、安装Vue CLI 查看npm版本号 &#xff08;可跳过&#xff09; % npm -v 11.0.0安装Vue CLI % npm install -g vue/cli2、创建项目 进入工程文件目录 % cd /Users/ruizhifeng/work/aina-client查看vue 版本号 &#xff08;可跳过&#xff09; % vue --version vue/cli 5…

ORB-SLAM3 RGBD摄像头

一、所需的环境 python2.7、Opencv3.2、Pangolin0.5、eigen3.3.1 Ubuntu18.04、ros版本&#xff1a;melodic 二、安装astro pro plus驱动 1、安装环境所需要依赖 sudo apt-get install ros-melodic-serial ros-melodic-bfl ros-melodic-mbf-msgs ros melodic-pointcloud-t…

Excel 技巧10 - 如何检查输入重复数据(★★)

本文讲了如何在Excel中通过COUNTIF来检查输入重复数据。 当输入重复数据时&#xff0c;显示错误提示。 1&#xff0c;通过COUNTIF来检查输入重复数据 比如下面是想检查不要输入重复的学号。 选中C列&#xff0c;点 Menu > 数据 > 数据验证 在数据验证页面&#xff0c…

SpringBoot的Bean-中级-作用域

5个作用域&#xff1a; 初级演示的是第一种默认的singleton&#xff1a;SpringBoot的Bean-初级获取bean对象-CSDN博客 中级-1&#xff1a;Lazy注解使其在使用的时候再实例化 中级-2&#xff1a;Scope("prototype")使其每次需要注入的时候都实例化新的对象 测试程序&…

4 AXI USER IP

前言 使用AXI Interface封装IP&#xff0c;并使用AXI Interface实现对IP内部寄存器进行读写实现控制LED的demo&#xff0c;这个demo是非常必要的&#xff0c;因为在前面的笔记中基本都需哟PS端与PL端就行通信互相交互&#xff0c;在PL端可以通过中断的形式来告知PS端一些事情&…