嚴華 发表于 昨天 21:57

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

需求

局域网设备主动发现是软件开辟中的一个常见且紧张的需求,它简化了设备间的协作机制,降低了软件各模块间举行复杂配置的需求。通过实现主动发现功能,不光明显提拔了用户的操作便捷性和满足度,还促进了网络资源的智能化分配与高效利用。为后续的通讯和传输奠定了基础。
局域网设备主动发现通常具有以下几个焦点功能:


[*]实时性:能够即时探测到局域网中新参加或脱离的设备,确保网络情况的实时更新。
[*]广泛性:支持多种范例的设备发现,包括但不限于计算机、打印机、智能家电、网络摄像头等。
[*]易用性:用户无需手动配置或输入设备的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 收到回声应答,表示连通性测试乐成。
[*]
抓包如下

https://i-blog.csdnimg.cn/direct/4c0e8af832404b9eb4f588b3963c2eca.png
代码实现

下面是简单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 = BROADCAST_MAC; /* Destination MAC address (Broadcast) */
    eh->ether_dhost = BROADCAST_MAC;
    eh->ether_dhost = BROADCAST_MAC;
    eh->ether_dhost = BROADCAST_MAC;
    eh->ether_dhost = BROADCAST_MAC;
    eh->ether_dhost = BROADCAST_MAC;
    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;
                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
https://i-blog.csdnimg.cn/direct/08f77c4e7b7b4fe3a8351e0d24c64137.png
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;}
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 局域网设备主动发现常用方法