ToB企服应用市场:ToB评测及商务社交产业平台

标题: 局域网设备主动发现常用方法 [打印本页]

作者: 嚴華    时间: 2024-9-19 21:57
标题: 局域网设备主动发现常用方法
需求

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

实现方法

ARP (Address Resolution Protocol)

   ARP是一种协议,用于将 IP地址解析成 MAC 地址。当主机想要与同一局域网内的另一台主机通讯时,它必要知道目标主机的 MAC 地址。ARP 就是用来完成这一使命的协议。ARP 哀求是通过广播方式举行的,所有接收到 ARP 哀求的设备都会查抄是否哀求的是自己的 IP 地址,如果是,则响应自己的 MAC 地址。
  Ping ip的流程

当你使用 Ping 向某个 IP 地址发送数据包时,首先必要知道该 IP 地址对应的 MAC 地址。这就是 ARP 的作用
一台计算机 A 要 Ping 另一台计算机 B,过程如下:

抓包如下


代码实现

下面是简单c语言示例,
使用原始套接字发送 ARP 哀求并接收 ARP 响应来获取局域网内所有在线设备的 IP 地址
安装 npm install libpcap-dev
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <sys/socket.h>
  6. #include <netinet/if_ether.h>
  7. #include <netinet/ip.h>
  8. #include <netinet/arp.h>
  9. #include <arpa/inet.h>
  10. #include <net/if.h>
  11. #include <ifaddrs.h>
  12. #define BROADCAST_MAC "\xff\xff\xff\xff\xff\xff"
  13. void send_arp_request(int sockfd, struct ether_header *eh, struct arphdr *arp, char *mac, char *ip, char *target_ip) {
  14.     memset(arp, 0, sizeof(struct arphdr));
  15.     arp->ar_hrd = htons(ARPHRD_ETHER);    /* Ethernet */
  16.     arp->ar_pro = htons(ETH_P_IP);       /* IP Protocol */
  17.     arp->ar_op  = htons(AROP_REQUEST);   /* ARP Request */
  18.     memcpy(arp->ar_saddr, mac, ETH_ALEN); /* Sender hardware address */
  19.     memcpy(arp->ar_sha, mac, ETH_ALEN);  /* Sender hardware address */
  20.     memcpy(arp->ar_tpa, inet_aton(target_ip), 4); /* Target protocol address */
  21.     memcpy(arp->ar_tha, "\x00\x00\x00\x00\x00\x00", 6); /* Target hardware address (all zeros) */
  22.     memcpy(arp->ar_spa, inet_aton(ip), 4); /* Sender protocol address */
  23.     eh->ether_dhost[0] = BROADCAST_MAC[0]; /* Destination MAC address (Broadcast) */
  24.     eh->ether_dhost[1] = BROADCAST_MAC[1];
  25.     eh->ether_dhost[2] = BROADCAST_MAC[2];
  26.     eh->ether_dhost[3] = BROADCAST_MAC[3];
  27.     eh->ether_dhost[4] = BROADCAST_MAC[4];
  28.     eh->ether_dhost[5] = BROADCAST_MAC[5];
  29.     eh->ether_type = htons(ETHER_TYPE_ARP); /* ARP Packet */
  30.     sendto(sockfd, eh, sizeof(struct ether_header) + sizeof(struct arphdr), 0, NULL, 0);
  31. }
  32. int main(void) {
  33.     struct ifaddrs *ifAddrStruct = NULL;
  34.     struct ifaddrs *tmpAddrPtr = NULL;
  35.     int sockfd;
  36.     char *target_ip = "192.168.1.0"; /* 目标 IP 地址段 */
  37.     int i = 0;
  38.     int len = 0;
  39.     /* 获取本地接口信息 */
  40.     if (getifaddrs(&ifAddrStruct) == -1) {
  41.         perror("getifaddrs");
  42.         return -1;
  43.     }
  44.     /* 打开原始套接字 */
  45.     if ((sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
  46.         perror("socket");
  47.         freeifaddrs(ifAddrStruct);
  48.         return -1;
  49.     }
  50.     tmpAddrPtr = ifAddrStruct;
  51.     while (tmpAddrPtr != NULL) {
  52.         if (tmpAddrPtr->ifa_addr != NULL && strcmp(tmpAddrPtr->ifa_name, "lo") != 0) {
  53.             char *ip = inet_ntoa(*(struct in_addr *)tmpAddrPtr->ifa_addr);
  54.             struct ether_header eh;
  55.             struct arphdr arp;
  56.             send_arp_request(sockfd, &eh, &arp, (char *)tmpAddrPtr->ifa_ifu.ifu_data, ip, target_ip);
  57.             /* 循环发送 ARP 请求 */
  58.             for (i = 1; i <= 254; i++) {
  59.                 char ipaddr[INET_ADDRSTRLEN];
  60.                 sprintf(ipaddr, "%s.%d", target_ip, i);
  61.                 send_arp_request(sockfd, &eh, &arp, (char *)tmpAddrPtr->ifa_ifu.ifu_data, ip, ipaddr);
  62.             }
  63.         }
  64.         tmpAddrPtr = tmpAddrPtr->ifa_next;
  65.     }
  66.     /* 清理 */
  67.     freeifaddrs(ifAddrStruct);
  68.     close(sockfd);
  69.     return 0;
  70. }
复制代码
mDNS


   在一个没有常规DNS服务器的小型网络内,可以使用mDNS来实现类似DNS的编程接口、包格式和操作语义。MDNS协议的报文与DNS的报文布局相同,但有些字段对于MDNS来说有新的含义。
  在局域网中,设备和设备之前相互通讯必要知道对方的ip地址的,大多数情况,设备的ip不是静态ip地址,而是通过dhcp 协议动态分配的ip 地址,mDNS如何设备发现呢,

对比测试

Avahi 先容

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

  1. yum install avahi libavahi-client-devel
复制代码

Avahi 使用

常用API
初始化
  1. avahi_init();
复制代码
创建 Avahi 客户端:
  1. AvahiClient *client;
  2. client = avahi_client_new(avahi_poll_get(), AVAHI_CLIENT_FLAG_USE_MULTICAST, NULL, NULL);
复制代码
回调监听状态变化
  1. static void client_callback(AvahiClient *client, AvahiClientState state, void *userdata) {
  2.     // 处理状态变化
  3. }
  4. avahi_client_set_callback(client, client_callback, NULL);
复制代码
测试代码

  1. #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();
  2.     /* 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企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4