网络编程 ----------- 4、组播与广播
1、广播 broadcast
广播是指向同一个网络中所有的主机传输数据只有传输层协议为 UDP协议时,才支持广播
TCP是端对端,广播是一对多 ,所以无法符合其要求。
1)广播地址
广播地址的计算:
子网掩码取反 再和 ip地址 进行按位或运算
例子: ip : 192.168.31.104netmask : 255.255.255.0 ===> 广播地址: 192.168.31.255 ip : 172.4.0.1 netmask :255.255.254.0 ===> 广播地址: 172.4.1.255 ip : 192.168.31.104netmask : 255.255.128.0 ===> 广播地址: 192.168.127.255
全网广播地址: 255.255.255.255
这个没有意义 --> 会造成网络风暴
2)广播的编程流程 (与UDP编程流程类似)
广播的发送者
广播接接收者
3)注意:设置套接字选项
谁需要用到广播, 谁就调用 setsockopt() 函数,设置套接字选项 (详细见表)
使能广播:
级别: SOL_SOCKET
选项: SO_BROADCAST
类型: int
0 禁用
非0 使能
写一个程序,实现 广播的发送和接收 broadcast_sender.c / broadcast_receiver.c broadcast_sender.c 发送者int main( int argc, char *argv[] ){//创建套接字 UDP int sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( sock_fd == -1 ){perror( "socket error " );return -1;}printf("sock_fd = %d\n", sock_fd );//设置套接字的选项 --> 使能广播 int n = 1;setsockopt( sock_fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n) );//设置广播的ip地址和端口号 struct sockaddr_in addr;addr.sin_family = AF_INET; //协议族 ipv4 addr.sin_port = htons( atoi(argv[2]) ); //端口号 inet_aton( argv[1], &addr.sin_addr ); //广播地址 //发送广播数据 while( 1 ){//输入要发送的数据 char buf[128] = {0};printf("input data : ");fgets( buf, sizeof(buf), stdin );int re = sendto( sock_fd, buf, strlen(buf), 0, (struct sockaddr*)&addr, sizeof(addr) );if( re == -1 ){perror( "sendto error " );break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//关闭套接字 close( sock_fd );}broadcast_receiver.c 接收者(服务器)int main( int argc, char *argv[] ){//创建套接字 UDP int sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( sock_fd == -1 ){perror( "socket error " );return -1;}printf("sock_fd = %d\n", sock_fd );//设置套接字的选项 --> 使能广播 int n = 1;setsockopt( sock_fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n) );//设置接收广播的ip地址和端口号 struct sockaddr_in addr;addr.sin_family = AF_INET; //协议族 ipv4 addr.sin_port = htons( atoi(argv[2]) ); //端口号 inet_aton( argv[1], &addr.sin_addr ); //广播地址 //绑定套接字 int re = bind( sock_fd, (struct sockaddr*)&addr, sizeof(addr) );if( re == -1 ){perror( "bind error " );close( sock_fd );return -1;}printf("bind success\n");//接收广播数据 while( 1 ){//接收数据 char buf[128] = {0};struct sockaddr_in from_addr;socklen_t len = sizeof(from_addr);re = recvfrom( sock_fd, buf, sizeof(buf), 0, (struct sockaddr*)&from_addr, &len );if( re > 0 ){printf("%s : %s\n", inet_ntoa(from_addr.sin_addr), buf );}else{perror( "recvfrom error " );break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//关闭套接字 close( sock_fd );}
2、组播 (多播) multicast
组播是指 将数据发送给 加入到某个组中的主机上
特点:
1)只有传输层协议为 UDP协议时,才支持组播功能
2)组播地址 ipv4 D类地址
D类地址: 1110 + 多播组号(28bits)
224.0.0.0 ~ 239.255.255.255
3)广播方式 占用带宽,会造成网络风暴
组播是一种折中的方式,只有加入到特定的 某个多播组的主机 才能收到数据
1)多播的代码实现
多播的发送者
多播的接收者
2)加入多播组
设置套接字的选项:
级别: IPPROTO_IP
选项: IP_ADD_MEMBERSHIP
类型: struct ip_mreqn {}
========================================
man 7 ip 进行查看
struct ip_mreqn
{
struct in_addr imr_multiaddr; /* 多播组地址(D类地址) (类似于qq群号)IP multicast group address */
struct in_addr imr_address; /* 接口(网卡)的地址,多播的数据实际走哪个网卡(类似于qq号) IP address of local interface */
...
};
struct in_addr
{
uint32_t s_addr; /* 32位IP地址 */
};
例子: 把 本机ip 加入多播组 224.0.0.1 struct ip_mreqn mreq;mreq.imr_multiaddr.s_addr = inet_addr( "224.0.0.1" ); //多播组地址 mreq.imr_address.s_addr = htonl( INADDR_ANY ); //接口地址 //mreq.imr_address.s_addr = inet_addr( argv[1] ); setsockopt( sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) );
注意:
要支持多播,需要设置路由表,让数据包从正确的网卡出去,而不是从默认网卡出去
首先 ifconfig 查看本机ip和网卡名字 (如: eth0, eth1, ens33, ... )
sudo route add -net 224.0.0.0 netmask 240.0.0.0 ens33 //加入路由表
sudo route add default gw 172.4.1.1 dev ens33 //设置默认网关
查看内核的IP路由标
route -n
练习: 写一个程序,实现多播的功能 multicast_sender.c / multicast_receiver.c multicast_sender.c 发送者multicast_receiver.c 接收者multicast_sender.c 发送者 int main( int argc, char *argv[] ){//创建套接字 UDP int sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( sock_fd == -1 ){perror( "socket error " );return -1;}printf("sock_fd = %d\n", sock_fd );//设置 多播的ip和端口号 struct sockaddr_in addr;addr.sin_family = AF_INET; //协议族 ipv4 addr.sin_port = htons( atoi(argv[2]) ); //端口号 inet_aton( argv[1], &addr.sin_addr ); //多播地址 224.0.0.1 //发送数据while(1){//发送数据 char buf[128] = {0};fgets( buf, sizeof(buf), stdin );int re = sendto( sock_fd, buf, strlen(buf), 0, (struct sockaddr*)&addr, sizeof(addr) );if( re == -1 ){perror( "sendto error " );break;}if( buf[0] == '#' ){break;}}//关闭套接字close( sock_fd );}multicast_receiver.c 接收者 int main( int argc, char *argv[] ){//创建套接字 UDP int sock_fd = socket( AF_INET, SOCK_DGRAM, 0 );if( sock_fd == -1 ){perror( "socket error " );return -1;}printf("sock_fd = %d\n", sock_fd );//设置套接字的选项 --> 把本机ip加入到多播组 224.0.0.1 struct ip_mreqn mreq;mreq.imr_multiaddr.s_addr = inet_addr( argv[1] ); //多播组地址 224.0.0.1 mreq.imr_address.s_addr = htonl( INADDR_ANY ); //接口地址 (本机地址)int re = setsockopt( sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq) ); if( re == -1 ){perror("add membership error ");close( sock_fd );return -1;}printf("add membership success\n");//设置 多播的ip和端口号 struct sockaddr_in addr;addr.sin_family = AF_INET; //协议族 ipv4 addr.sin_port = htons( atoi(argv[2]) ); //端口号 inet_aton( argv[1], &addr.sin_addr ); //多播地址 224.0.0.1 //设置端口号重用 int n = 1;setsockopt( server_sock, SOL_SOCKET, SO_REUSEPORT, &n, sizeof(n) );//绑定套接字 re = bind( sock_fd, (struct sockaddr*)&addr, sizeof(addr) );if( re == -1 ){perror( "bind error " );close( sock_fd );return -1;}printf("bind success\n");//接收数据while(1){//接收数据 char buf[128] = {0};struct sockaddr_in from_addr;socklen_t len = sizeof(from_addr);re = recvfrom( sock_fd, buf, sizeof(buf), 0, (struct sockaddr*)&from_addr, &len );if( re > 0 ){printf("%s : %s\n", inet_ntoa(from_addr.sin_addr), buf );}else {perror( "recvfrom error " );break;}//人为定义退出条件if( buf[0] == '#' ){break;}}//关闭套接字 close( sock_fd );}
相关文章:
网络编程 ----------- 4、组播与广播
1、广播 broadcast 广播是指向同一个网络中所有的主机传输数据只有传输层协议为 UDP协议时,才支持广播 TCP是端对端,广播是一对多 ,所以无法符合其要求。 1)广播地址 广播地址的计算: 子网掩码…...
最短路径算法:Bellman-Ford算法
引言 在图论中,Bellman-Ford算法是一种用于计算单源最短路径的算法。与Dijkstra算法不同,Bellman-Ford算法可以处理带有负权边的图,并且可以检测图中是否存在负权环。本文将详细介绍Bellman-Ford算法的定义、步骤及其实现。 Bellman-Ford算…...
爬虫:xpath模块及昵图网实例
xpath模块 from lxml import etreestr1 """ <div><ul><li class"item-0"><a href"link1.html">first item</a></li><li class"item-1"><a href"link2.html">second…...
高级java每日一道面试题-2024年8月03日-web篇-forward和redirect有什么区别?
如果有遗漏,评论区告诉我进行补充 面试官: forward和redirect有什么区别? 我回答: 在Java Web开发中,forward和redirect是Servlet容器提供的两种用于页面跳转的技术。它们的主要区别在于客户端感知的方式、URL地址的变化、请求对象的共享等方面。下面详细介绍两…...
如何让你的网站拥有更好的体验
在HTML中,属性是用于提供关于HTML元素的额外信息。接下来我们将讲解13个可以让用户拥有更好体验的HTML属性。 Accept 属性 我们可以在<input>元素(仅适用于文件类型)中使用accept属性来指定服务器可以接受的文件类型。 <input ty…...

opencascade AIS_TypeFilter AIS_XRTrackedDevice源码学习
opencascade AIS_TypeFilter 前言 通过它们的类型选择交互对象。该过滤器会对本地上下文中的每个交互对象提出问题, 以确定它是否具有非空的所有者,并且如果是,则检查它是否是所需类型。 如果对象在每种情况下都返回 true,则保留…...
使用Spring AOP监控指定方法执行时间
文章目录 一、加入pom依赖二、切面类和注解三、执行方法 一、加入pom依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>二、切面类和注解 import java.lang.…...

最新CSS3纵向菜单的实现
纵向菜单 通过下面例子,你会知道把列表转换成菜单的关键技术 a中的#是URL的占位符可以点击,真正用途中写实际URL <nav class"list1"><ul><li><a href"#">Alternative</a></li><li><…...
GooLeNet模型搭建
一、model import torch from torch import nn from torchsummary import summaryclass Inception(nn.Module):def __init__(self, in_channels, c1, c2 , c3 , c4):super(Inception, self).__init__()self.ReLU nn.ReLU()#路线1:1x1卷积self.p1_1 nn.Conv2d(in_channels i…...

使用ThreadLocal来存取单线程内的数据
一.什么是ThreadLocal? ThreadLocal,即线程本地变量。如果你创建了一个 ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是在操作自己本地内存里面的变量&…...

elasticsearch教程
1. 单点部署(rpm): #提前关闭firewalld,否则无法组建集群 #1. 下载ES rpm包 ]# https://www.elastic.co/cn/downloads #2. 安装es ]# rpm -ivh elasticsearch-7.17.5-x86_64.rpm #3. 调整内核参数(太低的话es会启动报错) echo "vm.max_map_count655360 fs.file-max 655…...

Arrays、Lambda表达式、Collection集合
1. Arrays 1.1 操作数组的工具类 方法名说明public static String toString(数组)把数组拼接成一个字符串public static int binarySearch(数组,查找的元素)二分查找法查找元素public static int[] copyOf(原数组,新数组长度)拷贝数组public static int[] copyOfRange(原数组…...

2024年前端趋势:全栈或许是不容错过的选择!
近年来,前端开发的技术不断推陈出新,2024年也不例外。在这个变化迅速的领域,全栈开发逐渐成为一股不容忽视的趋势。无论你是经验丰富的开发者,还是刚刚入门的新手,掌握全栈技术都能让你在竞争中脱颖而出。而在这个过程…...

MySQL 实战 45 讲(01-05)
本文为笔者学习林晓斌老师《MySQL 实战 45 讲》课程的学习笔记,并进行了一定的知识扩充。 sql 查询语句的执行流程 大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 Server 层包括连接器、查询缓存、分析器、优化器和执行器。 连接器负责接收客…...
仓颉编程语言入门 -- Array数组详解
仓颉编程语言入门 – Array数组详解 一. 如何创建Array数组 我们可以使用 Array 类型来构造单一元素类型,有序序列的数据。 1.仓颉使用 Array 来表示 Array 类型。T 表示 Array 的元素类型,T 可以是任意类型 , 类似于泛型的概念 var arr:Array<St…...
C#初级——简单单例模式使用
单例模式 单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,并提供一个全局访问点来获取这个实例,通过单例模式防止私有成员被多次引用,防止数据被随意纂改。本文使用的是线程不安全的懒汉式单例。 创建单例模式 首…...
2024.07.29 校招 实习 内推 面经
地/球🌍 : neituijunsir 交* 流*裙 ,内推/实习/校招汇总表格 1、校招 | 美/团// 快驴、小象、优/选/事/业/部2024年校/园/招聘(内推) 校招 | 美团快驴、小象、优选事业部2024年校园招聘(内推ÿ…...
速盾:爬虫攻击和cc攻击的区别是什么?
爬虫攻击和CC(Distributed Denial of Service)攻击是网络安全领域两种不同类型的攻击方式。尽管它们都涉及对目标网站或服务器的非法访问,但它们的目的、方法和影响各不相同。在接下来的文章中,我们将详细介绍这两种攻击方式的区别…...
Tomcat与Nginx的区别详解
目录 引言Tomcat概述 Tomcat的历史Tomcat的架构Tomcat的功能Nginx概述 Nginx的历史Nginx的架构Nginx的功能Tomcat与Nginx的区别 架构上的区别...

【大模型从入门到精通5】openAI API高级内容审核-1
这里写目录标题 高级内容审核利用 OpenAI 内容审核 API 的高级内容审核技术整合与实施使用自定义规则增强审核综合示例防止提示注入的策略使用分隔符隔离命令理解分隔符使用分隔符实现命令隔离 高级内容审核 利用 OpenAI 内容审核 API 的高级内容审核技术 OpenAI 内容审核 AP…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...

MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...