【Linux C | 网络编程】多播的概念、多播地址、UDP实现多播的C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍多播的概念、多播地址、UDP实现广播的C语言例子 🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
⏰发布时间⏰:2024-03-07 20:31:23
本文未经允许,不得转发!!!
目录
- 🎄一、多播概述
- 🎄二、多播地址
- ✨2.1、IPv4 多播地址
- ✨2.2、IPv6 多播地址
- ✨2.3、多播地址映射为MAC地址
- 🎄三、多播的过程
- 🎄四、源特定多播
- ✨4.1 广域网的多播
- ✨4.2 源特定多播(Source-Specific Multicast)
- 🎄五、UDP实现多播的例子
- ✨5.1 多播接收端代码
- ✨5.2 多播发送端代码
- 🎄六、总结
![]()
🎄一、多播概述
在网络编程中,有三种常见的通信方式:单播、广播、多播(组播),这三种方式对比如下表:
| 类型 | IPv4 | IPv6 | TCP | UDP | 所标识接口数 | 递送到的接口数 |
|---|---|---|---|---|---|---|
| 单播 | 支持 | 支持 | 支持 | 支持 | 一个 | 一个 |
| 广播 | 支持 | 支持 | 全体 | 全体 | ||
| 多播 | 可选 | 支持 | 支持 | 一组 | 整个组 |
多播的概念
IP 多播(也称多址广播或组播)技术,是允许一台主机向多台主机发送消息的一种通信方式。单播只向单个IP接口发送数据,广播是向子网内所有IP接口发送数据,多播则介于两者之间,向一组IP接口发送数据。
多播支持IPv4,也支持IPv6。在IPv6中没有广播,认为广播只是特殊(把整个子网视为多播组)的多播。
多播支持UDP,不支持TCP。
多播既可用于局域网,也可用于广域网,而广播一般在局域网使用。
多播的优点
比起广播,多播数据报只会发送到加入多播组的主机,不会像广播那样发给所有主机。
![]()
🎄二、多播地址
多播地址用来标识多播组,IPv4使用D类地址的某一个来表示一个多播组地址,IPv6多播地址的高序字节值为ff。
✨2.1、IPv4 多播地址
IPv4的D类地址(从224.0.0.0到239.255.255.255)是IPv4多播地址,见下图:

D类地址的低序28位构成多播组ID(group ID),整个32位地址则称为组地址(group address)。
IPv4的多播地址可分为三类:
- 链路局部多播地址:
224.0.0.0到224.0.0.255,这是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包; - 预留多播地址:
224.0.1.0到238.255.255.255,可用于全球范围(如Internet)或网络协议。 - 管理权限多播地址:
239.0.0.0到239.255.255.255,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围。
下面是若干个IPv4特殊多播地址,这些地址是由IANA确定的,作为永久主机组:
224.0.0.1 所有组播主机
224.0.0.2 所有组播路由器
224.0.0.4 DRMRP 路由器
224.0.0.5 所有 OSPF 的路由器
224.0.0.6 OSPF 指派路由器
224.0.0.9 RPIv2 路由器
224.0.0.10 EIGRP 路由器
224.0.0.13 PIM 路由器
224.0.0.22 IGMPv3
224.0.0.25 RGMP
224.0.1.1 NTP 网络时间协议
✨2.2、IPv6 多播地址
IPv6多播地址的结构如下图,分成4个部分:
- 高位8比特:全部为1,这是固定的,表示这是一个多播地址;
- 标志4比特:分以下几种取值
0000:众所周知的多播组;
0001:临时的多播组;
0010:表示多播地址是基于某个单播前缀赋予的;
0011:表示基于单播的多播地址总是临时的。 - 范围4比特:可能有以下取值
0:保留。
1:接口本地范围(Interface-Local scope )。
2:链路本地范围(Link-Local scope )。
3:基于单播前缀的地址(Unicast-Prefix-based address )。
4:管理本地范围(Admin-Local scope )。
5:站点本地范围(Site-Local scope)。
6:未分配。
7:汇聚点标记(Rendezvous Point flag )。
8:组织本地范围(Organization-Local scope )。
9-D:未分配。
E:全局范围(Global scope。
F:保留。 - 组ID112比特:低序32位复制到以太网地址的低序32位

下面是若干特殊的IPv6多播地址。
ff01::1和ff02::1是所有节点(all-nodes)组。子网上所有具有多播能力的节点(主机、路由器和打印机等)必须在所有具有多播能力的接口上加入该组,类似于IPv4的224.0.0.1多播地址。但多播是IPv6的一个组成部分,这与IPv4是不同的。
尽管对应的IPv4组称为所有主机组,而IPv6组称为所有节点组,它们的含义是一致的。IPv6重新命名意在更为清晰地指出本组包括了子网上的主机、路由器、打印机,以及任何IP设备。ff01::2、ff02::2和ff05::2是所有路由器(all-routers)组。子网上所有多播路由器必须在所有具有多播能力的接口上加入该组,类似于IPv4的224.0.0.2多播地址。
✨2.3、多播地址映射为MAC地址
将多播地址映射到以太网多播地址的过程是重要的,因为以太网是数据链路层的协议,而IPv4、IPv6的多播地址是网络层的协议。这种映射使得多播数据能够在以太网上正确传输到目标设备,确保只有加入了相应多播组的设备才会接收到相应的多播数据包。
以太网地址,通常称为MAC地址(Media Access Control address),是网络设备在数据链路层使用的唯一标识符。MAC地址由48位二进制数组成,通常以十六进制表示,每6位之间用冒号或连字符分隔,如 00:1A:2B:3C:4D:5E。通常,MAC地址是网络设备(如网卡)出厂设置好的,一般不会改变。
当一个IPv4多播数据包需要发送到多个接收者时,IPv4多播地址会被映射成对应的以太网多播地址。这种映射不会改变设备的硬件MAC地址,而是针对特定的多播传输而生成的临时多播MAC地址。多播MAC地址是一个虚拟的地址,源主机将数据发送到多播组对应的以太网多播地址,而不会影响到设备的真实MAC地址。设备仍然使用其固定的硬件MAC地址来标识自己,只是在多播通信过程中会使用临时的多播MAC地址来传输数据。

IPv4多播地址是通过特定规则映射到以太网多播地址的,映射规则如下:
- 前24位以固定的前缀
01:00:5E开头,第25位总是0。- 后23位直接由IPv4多播地址的低23位组成。IPv4多播地址高序4位固定为
e,映射过程中,中间的5位被忽略,因此这个映射关系不是一对一的。
IPv6多播地址到以太网地址的映射是通过多播组里的成员关系进行的。下面是IPv6多播地址到以太网地址的映射过程:
- 首先确定IPv6多播地址的范围,IPv6多播地址通常在ff00::/8的范围内。
- 多播组的最低24位用于构建对应的以太网地址。这个过程使用了特殊的前缀:33:33。
- 取IPv6多播地址的最低32位,将其转换为16进制,并插入到33:33之后,形成完整的以太网地址。
- 以太网地址的第一个字节设置为01-00-5E。这个步骤可以保证以太网地址不会与单播地址冲突。
总的来说,IPv6多播地址到以太网地址的映射是通过将IPv6多播地址的一部分直接复制到以太网地址中,并添加特定的前缀来确保唯一性。
![]()
🎄三、多播的过程
下图是可以展示多播的过程:

多播的过程:
- 首先,接收主机(图中右侧)需要在接收进程创建一个UDP套接字,绑定端口123,然后加入多播组
224.0.1.1。该主机的IPv4层会保存这些信息,并告知合适的数据链路接收目的以太网地址为01:00:5e:00:01:01的以太网帧。 - 然后,发送主机(图中左侧)的发送应用进程创建一个UDP套接字,往IP地址
224.0.1.1的123端口发送一个数据报,并最后转换成以太网帧发到网络。发送多播数据报无需任何特殊处理,发送应用进程不必为此加入多播组。 - 接着,不具备多播能力的主机(图中中间主机)会完全忽略该帧。因为:
1、该帧的目的以太网地址不匹配该主机的接口地址;
2、该帧的目的以太网地址不是以太网广播地址;
3、该主机的接口未被告知接收任何组地址(高序字节的低序位被置为1的以太网地址,如图21-1所示)。 - 最后,接收主机(图中右侧)的数据链路收取该帧后将承载的分组传递到IP层。IP层比较该地址和本机的接收应用进程已经加入的所有多播地址,根据比较结果确定是接受还是丢弃该分组。确定接受之后,再把承载的UDP数据报传递到UDP层。UDP层再把承载在数据报中的数据传递到绑定了端口123的套接字。
图中没有展示的还有以下三种情形:
- (1)运行所加入多播地址为225.0.1.1的某个应用进程的一个主机。既然多播地址组ID的高5位在到以太网地址的映射中被忽略,该主机的接口也将接收目的以太网地址为
01:00:5e:00:01:01的帧。这种情况下,由该帧承载的分组将由IP层中的完备过滤丢弃。 - (2)运行所加入多播地址符合以下条件的某个应用进程的一个主机:由这个多播地址映射成的以太网地址恰好和
01:00:5e:00:01:01一样被该主机执行非完备过滤的接口散列到同一个结果。该接口也将接收目的以太网地址为01:00:5e:00:01:01的帧,直到由数据链路层或IP层丢弃。 - (3)目的地为相同多播组(
224.0.1.1)不同端口(譬如4000)的一个数据报。图21-4中右侧主机仍然接收该数据报,并由P层接受并传递给UDP层,不过UDP层将丢弃它(假设绑定端口4000的套接字不存在)。
![]()
🎄四、源特定多播
✨4.1 广域网的多播
多播是不仅支持局域网,也支持广域网。
当某个主机上的一个进程加入一个多播组时,该主机向所有直接连接的多播路由器发送一个IGMP消息,告知它们本主机已加入了那个多播组。多播路由器随后使用多播路由协议(MRP)交换这些信息,这样每个多播路由器就知道在收到目的地为所加入多播地址的分组时该如何处理。
✨4.2 源特定多播(Source-Specific Multicast)
源特定多播的英文是Source-Specific Multicast,简称SSM,是基于源地址和目的地址的组合来定义多播组,接收者只能从单个源(或称为发送者)接收数据,而不是从任意源接收,这使得网络更加安全可靠。
- 接收进程向多播路由器提供发送进程的
源地址作为多播组加入操作的一部分。这种方式可以减少网络中的不必要流量,提高网络效率。 - 把多播组的标识从单纯多播组地址细化为单播源地址和多播目的地址之组合(SSM称之为通道)。
![]()
🎄五、UDP实现多播的例子
下面给出一个使用UDP实现多播的例子,代码是之前文章的例子修改的,文章链接: 入门知识:UDP协议、一个最简单的UDP客户端、一个最简单的UDP服务端 。
✨5.1 多播接收端代码
接收端是使用UDP服务端代码修改,需要在交互数据之前,将套接字加入多播组239.0.1.1,让链路层接口接收该多播组的数据报,使用完需要离开多播组。
UDP多播接收端步骤:
- 1、创建UDP套接字socket;
- 2、准备本地ip接口和多播组端口;
- 3、绑定多播组端口 bind;
- 4、加入多播组 239.0.1.1;
- 5、使用 sendto、recvfrom 交互数据;
- 6、离开多播组
- 7、关闭套接字
// multicastSer.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、加入多播组 239.0.1.1struct ip_mreq mreq;mreq.imr_multiaddr.s_addr = inet_addr("239.0.1.1"); // 多播组的IP地址mreq.imr_interface.s_addr = htonl(INADDR_ANY); // 加入的客服端主机IP地址if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {perror("setsockopt");return -1;}// 5、使用 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);}}// 6、离开多播组setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq)); // 7、关闭close(sockfd);return 0;
}
✨5.2 多播发送端代码
发送端是使用UDP客户端代码修改,整个流程都不需改动,只需要把要发送的目的地址改为多播组地址239.0.1.1。修改后代码如下:
// multicastCli.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、准备多播组地址和端口struct sockaddr_in servaddr;bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons (10086);if (inet_pton(AF_INET, "239.0.1.1", &servaddr.sin_addr) <= 0)perror("inet_pton error");// 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;
}
在4台机器运行多播接收端,下面是发送端的运行结果,发出多播数据报后,收到了各个接收端的回复:

![]()
🎄六、总结
👉本文介绍多播的概念,多播地址,多播数据报发送过程,最后给出C语言实现多播的例子。

如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁
相关文章:
【Linux C | 网络编程】多播的概念、多播地址、UDP实现多播的C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
AIGC实战——GPT(Generative Pre-trained Transformer)
AIGC实战——GPT 0. 前言1. GPT 简介2. 葡萄酒评论数据集3. 注意力机制3.1 查询、键和值3.2 多头注意力3.3 因果掩码 4. Transformer4.1 Transformer 块4.2 位置编码 5. 训练GPT6. GPT 分析6.1 生成文本6.2 注意力分数 小结系列链接 0. 前言 注意力机制能够用于构建先进的文本…...
微信小程序-入门
一.通过 Npm方式下载构建 1.下载和安装Npm:Npm https://docs.npmjs.com/downloading-and-installing-node-js-and-npm 或者 https://nodejs.org/en/download/ 未安装npm 提示 以下以安装node安装包为例 按任意键继续 安装完成后 2. 下载和安装小程序开…...
0102全排列和对换-行列式-线性代数
把n个不同的数排成一列,叫做这n个数的全排列(排列)。 一般情况, 1 , 2 , ⋯ , n 1,2,\cdots,n 1,2,⋯,n是n个数排列的标准次序。 当n个数的任一排列中两个数的先后次序与标准次序不同时,有说有一个逆序。 一个排列中所…...
面向对象的编程语言是什么意思?——跟老吕学Python编程
面向对象的编程语言是什么意思?——跟老吕学Python编程 面向对象是什么意思?面向对象的定义面向对象的早期发展面向对象的背景1.审视问题域的视角2.抽象级别3.封装体4.可重用性 面向对象的特征面向对象的开发方法面向对象程序设计基本思想实现 面向对象的…...
Spring Boot整合MyBatis Plus配置多数据源
Spring Boot 专栏:https://blog.csdn.net/dkbnull/category_9278145.html Spring Cloud 专栏:https://blog.csdn.net/dkbnull/category_9287932.html GitHub:https://github.com/dkbnull/SpringBootDemo Gitee:https://gitee.com/…...
Unix Network Programming Episode 88
‘inetd’ Daemon On a typical Unix system, there could be many servers in existence, just waiting for a client request to arrive. Examples are FTP, Telnet, Rlogin, TFTP, and so on. With systems before 4.3BSD, each of these services had a process associate…...
Java面试题之11MySQL
你对MySQL执行计划怎么看 执行计划就是SQL的执行查询的顺序,以及如何使用索引查询,返回的结果集的行数 在MySQL中,我们可以通过explain命令来查看执行计划。其语法如下: EXPLAIN SELECT * FROM table_name WHERE conditions;在…...
R语言:多值提取到点
ArcGIS中有相关工具实现多值提取到点的功能,在这里,我将使用R语言进行操作: library(dplyr) library(readxl) library(sf) library(raster)setwd("D:/Datasets") Bio <- stack(paste0("D:/Datasets/Data/worldclim2_1km/…...
八股文打卡day27——数据库(4)
面试题:讲一下事务的隔离级别? 我的回答: 因为事务之间的隔离性,造成了一些问题,比如说:脏读、不可重复读和幻读(虚读)。 1.什么叫脏读? 就是一个事务读取到了另一个事…...
Java桥接模式源码剖析及使用场景
目录 一、介绍二、项目管理系统中使用桥接模式三、权限管理中使用桥接模式四、Java JDBC中使用桥接模式 一、介绍 它的主要目的是将抽象化与实现化分离,使得二者可以独立变化,就像一个桥,将两个变化维度连接起来。各个维度都可以独立的变化。…...
【异常处理】verilator安装时出现异常 make: *** [Makefile:195: verilator_gantt.1] Error 13
在ubuntu中安装verilator工具时执行make出现该报错。 当我出现这个报错的时候我一脸懵逼,因为网上找不到相关解决办法。 后来想到我的verilator是从github上下载zip,然后解压后传到ubuntu上的,windows上解压我记得会把-替换成_,这…...
测试一下 Anthropic 宣称超过 GPT-4 的 Claude 3 Opus
测试一下 Anthropic 宣称超过 GPT-4 的 Claude 3 Opus 0. 引言1. 测试 Claude 3 Opus3. 试用 api key 限制 0. 引言 今天测试一下 Anthropic 发布的 Claude 3 Opus。 3月4日,Anthropic 宣布推出 Claude 3 型号系列,该系列在广泛的认知任务中树立了新的…...
【题解】—— LeetCode一周小结10
【题解】—— 每日一道题目栏 上接:【题解】—— LeetCode一周小结9 4.用栈实现队列 题目链接:232. 用栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):…...
Android studio虚拟调试出现“我的APP keeps stopping”问题
问题如图: 遇到这种情况,一看代码,也没有报错呀,怎么不能运行呢?不要慌!我们一步一步来。 1、查看Logcat日志 在Android Studio中查看Logcat窗口,可以获取应用程序崩溃时的详细错误信息&…...
【Web】浅聊Java反序列化之Spring2链——两层动态代理
目录 简介 简话JdkDynamicAopProxy 关于target的出身——AdvisedSupport EXP 请确保已阅读过前文或对Spring1链至少有一定认知:【Web】浅聊Java反序列化之Spring1链——三层动态代理-CSDN博客 简介 Spring2 和 Spring1 的反序列化过程基本相同,唯一…...
2386. 找出数组的第 K 大和
2386. 找出数组的第 K 大和 题目链接:2386. 找出数组的第 K 大和 代码如下: //优先队列 //参考:https://leetcode.cn/problems/find-the-k-sum-of-an-array/solutions/2668280/zhao-chu-shu-zu-de-di-k-da-he-by-leetcod-z5kq class Soluti…...
Pytorch学习 day10(L1Loss、MSELoss、交叉熵Loss)
Loss loss的作用如下: 计算实际输出和真实值之间的差距为我们更新模型提供一定的依据(反向传播) L1Loss 绝对值损失函数:在每一个batch_size内,求每个输入x和标签y的差的绝对值,最后返回他们平均值 M…...
2.2 传统经济学在耍赖
传统经济学中,主体的行为决策是研究的重点对幸福的追求不是传统经济学的研究重点,决策才是。在传统经济学那里,只要能搞清楚是什么决定了决策就可以了。 传统经济学用人们对物品的喜好的排序去替代了对幸福的直接度量。这样做有一个好处&…...
【算法面试题】-04
执行时长 def min_execution_time(n, size, tasks):a 0ans sizei 0while i < size:tmp tasks[i]a tmpif a < n:a 0else:a - ni 1ans a // nif a % n ! 0:ans 1return ans# 读取输入 n int(input()) size int(input()) tasks list(map(int, input().split()))…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
