局域网设备自动发现常用方法

文章目录

  • 需求
  • 实现方法
    • ARP (Address Resolution Protocol)
      • Ping ip的流程
      • 抓包如下
      • 代码实现
    • mDNS
  • 对比测试
    • Avahi 介绍
    • Avahi 安装
    • Avahi 使用
    • 测试代码

需求

局域网设备自动发现是软件开发中的一个常见且重要的需求,它简化了设备间的协作机制,降低了软件各模块间进行复杂配置的需求。通过实现自动发现功能,不仅显著提升了用户的操作便捷性和满意度,还促进了网络资源的智能化分配与高效利用。为后续的通信和传输奠定了基础。

局域网设备自动发现通常具有以下几个核心功能:

  • 实时性:能够即时探测到局域网中新加入或离开的设备,确保网络环境的实时更新。
  • 广泛性:支持多种类型的设备发现,包括但不限于计算机、打印机、智能家电、网络摄像头等。
  • 易用性:用户无需手动配置或输入设备的IP地址等信息,即可轻松访问和使用这些设备。
  • 安全性:在自动发现设备的同时,也考虑到了网络安全问题,如防止未授权设备的接入等。

实现方法

ARP (Address Resolution Protocol)

ARP是一种协议,用于将 IP地址解析成 MAC 地址。当主机想要与同一局域网内的另一台主机通信时,它需要知道目标主机的 MAC 地址。ARP 就是用来完成这一任务的协议。ARP 请求是通过广播方式进行的,所有接收到 ARP 请求的设备都会检查是否请求的是自己的 IP 地址,如果是,则响应自己的 MAC 地址。

Ping ip的流程

当你使用 Ping 向某个 IP 地址发送数据包时,首先需要知道该 IP 地址对应的 MAC 地址。这就是 ARP 的作用

一台计算机 A 要 Ping 另一台计算机 B,过程如下:

  • A 查询自己的 ARP 缓存表,看是否有 B 的 IP 地址对应的 MAC 地址记录。
  • 如果找不到,则 A 发送一个 ARP 请求到局域网内所有设备(广播),询问谁拥有 B 的 IP 地址。
  • B 接收到 ARP 请求后,如果匹配自己的 IP 地址,就回复 ARP 响应给 A,告诉它自己的 MAC 地址。
  • A 收到 ARP 响应后,记录下 B 的 MAC 地址,并更新 ARP 缓存表。
  • A 然后构造一个 ICMP Echo Request 数据包,并使用 B 的 MAC 地址发送给 B。
  • B 收到 ICMP Echo Request 后,回应一个 ICMP Echo Reply 给 A。
  • A 收到回声应答,表示连通性测试成功。

抓包如下

在这里插入图片描述

代码实现

下面是简单c语言示例,
使用原始套接字发送 ARP 请求并接收 ARP 响应来获取局域网内所有在线设备的 IP 地址

安装 npm install libpcap-dev

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/arp.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <ifaddrs.h>#define BROADCAST_MAC "\xff\xff\xff\xff\xff\xff"void send_arp_request(int sockfd, struct ether_header *eh, struct arphdr *arp, char *mac, char *ip, char *target_ip) {memset(arp, 0, sizeof(struct arphdr));arp->ar_hrd = htons(ARPHRD_ETHER);    /* Ethernet */arp->ar_pro = htons(ETH_P_IP);       /* IP Protocol */arp->ar_op  = htons(AROP_REQUEST);   /* ARP Request */memcpy(arp->ar_saddr, mac, ETH_ALEN); /* Sender hardware address */memcpy(arp->ar_sha, mac, ETH_ALEN);  /* Sender hardware address */memcpy(arp->ar_tpa, inet_aton(target_ip), 4); /* Target protocol address */memcpy(arp->ar_tha, "\x00\x00\x00\x00\x00\x00", 6); /* Target hardware address (all zeros) */memcpy(arp->ar_spa, inet_aton(ip), 4); /* Sender protocol address */eh->ether_dhost[0] = BROADCAST_MAC[0]; /* Destination MAC address (Broadcast) */eh->ether_dhost[1] = BROADCAST_MAC[1];eh->ether_dhost[2] = BROADCAST_MAC[2];eh->ether_dhost[3] = BROADCAST_MAC[3];eh->ether_dhost[4] = BROADCAST_MAC[4];eh->ether_dhost[5] = BROADCAST_MAC[5];eh->ether_type = htons(ETHER_TYPE_ARP); /* ARP Packet */sendto(sockfd, eh, sizeof(struct ether_header) + sizeof(struct arphdr), 0, NULL, 0);
}int main(void) {struct ifaddrs *ifAddrStruct = NULL;struct ifaddrs *tmpAddrPtr = NULL;int sockfd;char *target_ip = "192.168.1.0"; /* 目标 IP 地址段 */int i = 0;int len = 0;/* 获取本地接口信息 */if (getifaddrs(&ifAddrStruct) == -1) {perror("getifaddrs");return -1;}/* 打开原始套接字 */if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {perror("socket");freeifaddrs(ifAddrStruct);return -1;}tmpAddrPtr = ifAddrStruct;while (tmpAddrPtr != NULL) {if (tmpAddrPtr->ifa_addr != NULL && strcmp(tmpAddrPtr->ifa_name, "lo") != 0) {char *ip = inet_ntoa(*(struct in_addr *)tmpAddrPtr->ifa_addr);struct ether_header eh;struct arphdr arp;send_arp_request(sockfd, &eh, &arp, (char *)tmpAddrPtr->ifa_ifu.ifu_data, ip, target_ip);/* 循环发送 ARP 请求 */for (i = 1; i <= 254; i++) {char ipaddr[INET_ADDRSTRLEN];sprintf(ipaddr, "%s.%d", target_ip, i);send_arp_request(sockfd, &eh, &arp, (char *)tmpAddrPtr->ifa_ifu.ifu_data, ip, ipaddr);}}tmpAddrPtr = tmpAddrPtr->ifa_next;}/* 清理 */freeifaddrs(ifAddrStruct);close(sockfd);return 0;
}

mDNS

  • mDNS(Multicast DNS)协议:使用5353端口,组播地址 224.0.0.251。

在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口、包格式和操作语义。MDNS协议的报文与DNS的报文结构相同,但有些字段对于MDNS来说有新的含义。

在局域网中,设备和设备之前相互通信需要知道对方的ip地址的,大多数情况,设备的ip不是静态ip地址,而是通过dhcp 协议动态分配的ip 地址,mDNS如何设备发现呢,

  • UPnP(Universal Plug and Play)技术:UPnP技术旨在让智能设备能够自动发现网络上的其他UPnP设备,并与之进行通信和协作。它支持设备之间的动态服务发现、自动配置和事件通知等功能。
  • LLMNR(Link-Local Multicast Name Resolution)协议:作为DNS的一种补充,LLMNR协议在局域网内通过多播方式解析设备的名称和地址。它特别适用于IPv6网络环境,并能够在DNS服务不可用的情况下提供快速的名称解析服务。
  • SNMP(Simple Network Management Protocol)协议:虽然SNMP主要用于网络管理而非设备发现,但它可以通过轮询网络中的设备来收集其状态信息,从而间接实现设备发现的目的。通过SNMP,管理员可以获取设备的型号、序列号、固件版本等详细信息。
  • 自定义协议

对比测试

Avahi 介绍

Avahi 是一个开源项目,提供了一套用于实现 mDNS (Multicast DNS) 和 SSDP (Simple Service
Discovery Protocol) 的工具和库。它主要用于局域网内的零配置网络服务发现。Avahi 支持多种操作系统,包括 Linux、BSD 变体以及其他类 Unix 系统。
Avahi 库的主要用途

  • 服务发现: 让设备在本地网络中自动发现彼此提供的服务。
  • 名称解析: 自动解析设备和服务的名称到 IP 地址,而无需手动配置。
  • 广告服务: 让设备能够发布自己提供的服务,以便其他设备可以发现。
  • 多播 DNS: 利用 mDNS 进行服务发现和名称解析。
  • 简单服务发现协议: 通过 SSDP 进行服务发现

Avahi 安装

yum install avahi libavahi-client-devel

在这里插入图片描述

Avahi 使用

常用API
初始化

avahi_init();

创建 Avahi 客户端:

AvahiClient *client;
client = avahi_client_new(avahi_poll_get(), AVAHI_CLIENT_FLAG_USE_MULTICAST, NULL, NULL);

回调监听状态变化

static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) {// 处理状态变化
}
avahi_client_set_callback(client, client_callback, NULL);

测试代码

#include <avahi-common/poll.h>
#include <avahi-core/core.h>
#include <avahi-client/client.h>
#include <stdio.h>
#include <stdlib.h>static void service_resolved(AvahiServiceResolvedEvent *event, void *userdata) {printf("Found service '%s' at '%s', port %d.\n",event->name, event->address, event->port);
}static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) {AvahiEntryGroup *group;AvahiEntryGroupState group_state;AvahiServiceResolver *res;if (state != AVAHI_CLIENT_S_RUNNING)return;/* Create a new entry group */if ((group = avahi_client_new_entry_group(client)) == NULL) {fprintf(stderr, "No memory, aborting.\n");return;}/* Setup callback for the entry group */avahi_entry_group_set_callback(group, entry_group_state_callback, userdata);/* Add a service browser to the entry group */if (avahi_entry_group_add_service_browser(group,AVAHI_IF_UNSPECIFIED,AVAHI_PROTO_INET,"_service._tcp", NULL, NULL) < 0) {fprintf(stderr, "Could not add service browser to entry group.\n");avahi_entry_group_free(group);return;}/* Commit the entry group */if (avahi_entry_group_commit(group) < 0) {fprintf(stderr, "Could not commit entry group.\n");avahi_entry_group_free(group);return;}/* Wait until the entry group is ready */do {avahi_entry_group_get_state(group, &group_state);} while (group_state != AVAHI_ENTRY_GROUP_COMMITTED);/* Now we can resolve services */if ((res = avahi_client_alloc_service_resolver(client)) == NULL) {fprintf(stderr, "No memory, aborting.\n");return;}avahi_service_resolver_set_callback(res, service_resolved, NULL);/* Resolve the first found service */avahi_service_resolver_resolve(res,AVAHI_IF_UNSPECIFIED,AVAHI_PROTO_INET,"my-service", "local", NULL);
}int main(int argc, char *argv[]) {AvahiClient *client;AvahiClientState initial_state;/* Initialize Avahi library */avahi_init();/* Create a new client object */if ((client = avahi_client_new(avahi_poll_get(), AVAHI_CLIENT_FLAG_USE_MULTICAST, client_callback, NULL)) == NULL) {fprintf(stderr, "Failed to create client.\n");return 1;}/* Get the initial client state */avahi_client_get_state(client, &initial_state);/* Main loop */while (initial_state != AVAHI_CLIENT_S_RUNNING) {avahi_client_wait(client, 1000);avahi_client_get_state(client, &initial_state);}/* Clean up */avahi_client_free(client);return 0;
}

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

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

相关文章

实验九 多线程的处理

实验目的及要求 目的&#xff1a;理解线程的概念&#xff0c;掌握Java的多线程机制&#xff0c;会用多线程编写Java程序。 要求&#xff1a; 理解线程的概念会用Thread类创建线程会使用Runnable接口创建多线程对两种实现多线程方式的方式进行对比掌握线程的同步 二、实验环境…

Vue 中实现视频播放的艺术

随着前端技术的飞速发展&#xff0c;视频播放在 Web 应用中已经成为了一个不可或缺的功能。从社交媒体平台到教育网站&#xff0c;再到在线购物平台&#xff0c;视频元素无处不在。而 Vue.js 作为当今最流行的前端框架之一&#xff0c;在实现视频播放时提供了很多强大的工具和技…

项目日志——日志器模块的设计、同步日志器实现、测试

文章目录 日志器模块设计同步日志器实现测试 日志器模块 设计 日志器模块的主要功能就是将前面的所有模块进行整合&#xff0c;向外提供接口&#xff0c;完成不同等级日志的输出 需要管理的成员有 格式化模块的对象落地模块的对象组当前默认的输出等级互斥锁日志器名称各个…

Pygame中Sprite类实现多帧动画3-3

4 使用自定义类MySprite 使用自定义类MySprite实现多帧动画的步骤是首先创建MySprite类的实例&#xff0c;之后使用相关函数对该实例进行操作。 4.1 创建MySprite类的实例 创建MySprite类的实例的代码如图12所示。 图12 创建MySprite类的实例的代码 其中&#xff0c;变量dr…

TortoiseGit无法安装解决方案

Win11安装TortoiseGit报错&#xff0c;错误码&#xff1a;2503&#xff0c;如下图&#xff1a; 开始-右键-Windows PowerShell&#xff08;管理员&#xff09;/终端 (管理员) 输入 msiexec /package 安装程序所在绝对路径&#xff0c; 例如 : msiexec /package D:\我的资料…

利用鸢尾花数据集介绍PCA算法

PCA&#xff1a; 主成分分析&#xff08;PCA, Principal Component Analysis&#xff09;是一种常用的数据降维技术&#xff0c;它可以将高维数据转换为较低维数据&#xff0c;同时尽可能保留数据的主要信息。PCA通过寻找数据的主要方向&#xff0c;即方差最大的方向&#xff0…

小小GCD、LCM拿下拿下

目录 最大公约数&#xff08;GCD&#xff09; 最大公约数&#xff08;GCD&#xff09;求解&#xff1a; 一、辗转相除法 二、三目运算符 三、位运算 最大公约数&#xff08;GCD&#xff09;模板&#xff1a; 最大公约数&#xff08;GCD&#xff09;例题&#xff1a; 最…

stm32之硬件SPI读写W25Q64存储器应用案例

系列文章目录 1. stm32之SPI通信协议 2. stm32之软件SPI读写W25Q64存储器应用案例 3. stm32之SPI通信外设 文章目录 系列文章目录前言一、电路接线图二、应用案例代码三、应用案例代码分析3.1 基本思路3.2 相关库函数介绍3.3 MySPI模块3.3.1 模块初始化3.3.2 SPI基本时序单元模…

丰巢“闯关”港交所上市

社区中随处可见的智能快递柜&#xff0c;即将捧出一个IPO。 近日&#xff0c;丰巢控股有限公司&#xff08;下称“丰巢控股”或“丰巢”&#xff09;正式向港交所递交了招股书&#xff0c;华泰国际担任其独家保荐人。这将是继顺丰控股、顺丰房托、嘉里物流、顺丰同城之后&…

微服务CI/CD实践(六)Jenkins Docker 自动化构建部署Java微服务

微服务CI/CD实践系列&#xff1a; 微服务CI/CD实践&#xff08;一&#xff09;环境准备及虚拟机创建 微服务CI/CD实践&#xff08;二&#xff09;服务器先决准备 微服务CI/CD实践&#xff08;三&#xff09;gitlab部署及nexus3部署 微服务CI/CD实践&#xff08;四&#xff09…

未来餐饮革命:加入我们的智能餐厅代理、自主开拓市场计划!

系统开发集成商&#xff1a;如果您正在开发智慧餐厅系统&#xff0c;忙于寻找各种消费终端接入、那么我们将可以为您提供整套智慧餐厅系统解决方案&#xff0c;从前厅消费到后厨的明厨亮灶的解决方案。 集团公司&#xff1a;想集团化控制子公司食堂运营&#xff0c;又想以最低…

【LeetCode每日一题】——LCR 168.丑数

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目注意】六【题目示例】七【题目提示】八【解题思路】九【时间频度】十【代码实现】十一【提交结果】 一【题目类别】 优先队列 二【题目难度】 中等 三【题目编号】 LCR 168.丑数 四【题目描述…

uts+uniapp踩坑记录(vue3项目

杂记&#xff1a; web-view方面 内嵌html使用web-view时&#xff0c;直接用 uni.postMessage({data: {action: message // 你要传的信息}}); 示例上写的是用 document.addEventListener(UniAppJSBridgeReady, function() { uni.postMessage({ data: { action: postMe…

nohup与

在 Unix/Linux 系统中&#xff0c;nohup 命令和 & 符号都是用来在后台运行命令的工具&#xff0c;但它们有一些区别。 nohup nohup 命令允许你在终端关闭之后继续运行进程。通常情况下&#xff0c;当你退出终端会话时&#xff0c;正在运行的进程会被挂断&#xff08;SIGH…

【大数据】Hadoop里的“MySQL”——Hive,干货满满

【大数据】Hadoop里的“MySQL”——Hive&#xff0c;干货满满 文章脉络 Hive架构 HQL 表类型 创建表语法 分区 数据导入导出 函数 内置函数 UDF Java Python 在阅读本文前&#xff0c;请确保已经对Hadoop的三大组件&#xff08;HDFS、MapReduce、YARN&#xff09;有…

分布式协调服务--ZooKeeper

文章目录 ZooKeeperzk的由来zk解决了什么问题 ZK工作原理ZK数据模型zk功能1.命名服务2.状态同步3.配置中心4.集群管理 zk部署单机启动zk验证zk zk集群集群角色选举过程1.节点角色状态2.选举ID3.具体过程4.心跳机制5.ZAB协议 ZooKeeper 选举示例1.第一轮投票&#xff1a;2.节点收…

以下是分析执行计划中索引使用情况的方法:

一、查看是否使用索引 执行计划通常会明确显示是否使用了索引。如果没有使用索引&#xff0c;可能会看到类似“全表扫描”的描述。例如&#xff1a; “TABLE ACCESS FULL (table_name)”表示对表进行了全表扫描&#xff0c;没有使用索引。 如果使用了索引&#xff0c;会有…

《React Native 应用开发最佳实践》

⭐️React Native 应用开发最佳实践⭐️ 近年来&#xff0c;React Native 应用开发因其能够使用 JavaScript 构建原生移动应用的能力而大受欢迎。它提供了跨平台兼容性、更快的开发时间以及更易于维护的特性&#xff0c;成为了许多开发者的首选。然而&#xff0c;要确保 React…

Unity TextMeshPro 设置竖排

默认竖排是这样的 但是我们要的竖排效果并不是这样我们要是竖排连续的根据文本限制来进行换行 第一步我们先设置文本的旋转Z轴为90如下图 然后我们给文本加一个Tag <rotate270> 如下图 但是这个效果还是不是我们想要的效果我们可以使用TexeMeshPro提供的一个选项EnableR…

Python画笔案例-041 绘制正方形阶梯

1、绘制正方形阶梯 通过 python 的turtle 库绘制正方形阶梯&#xff0c;如下图&#xff1a; 2、实现代码 绘制正方形阶梯&#xff0c;以下为实现代码&#xff1a; """正方形阶梯.py """ import turtledef draw_square(length):for _ in range(6…