zoukankan      html  css  js  c++  java
  • 使用 SendARP 获取 MAC 地址(使用SendARP API函数,很多相关文章)

    ARP 协议
    地址解析协议(ARP)是通过解析网路层地址来找寻数据链路层地址的一个在网络协议包中极其重要的网络传输协议。ARP 最初在 1982 年的 RFC 826 中提出并纳入互联网标准 STD 37. ARP 也可能指是在多数操作系统中管理其相关地址的一个进程。

    ARP 是通过网络地址(例:IPv4)来定位 MAC 地址(也称为乙太地址)。ARP 已经在很多网路层和数据链接层之间得以实现,包括:IPv4,Chaosnet,DECnet 和 Xerox PARC Universal Packet (PUP) 使用 IEEE 802 标准,光纤分布式数据接口,X.25,帧中继和异步传输模式(ATM),IEEE 802.3 和 IEEE 802.11 标准上 IPv4 占了多数流量。

    在 IPv6 中邻居发现协议(NDP)用于代替地址解析协议。

    ARP 基本原理
    在每台安装有 TCP/IP 协议的计算机或路由器里都有一个 ARP 缓存表,表里的 IP 地址与 MAC 地址是一对应的,如下表所示:

    主机名称 IP 地址 MAC 地址
    A 192.168.38.10 00-AA-00-62-D2-02
    B 192.168.38.11 00-BB-00-62-C2-02
    C 192.168.38.12 00-CC-00-62-C2-02
    D 192.168.38.13 00-DD-00-62-C2-02
    E 192.168.38.14 00-EE-00-62-C2-02
    … … …
    以主机 A(192.168.38.10)向主机 B(192.168.38.11)发送数据为例:

    当发送数据时,主机 A 会在自己的 ARP 缓存表中寻找是否有目标 IP 地址。如果找到就知道目标 MAC 地址为(00-BB-00-62-C2-02),直接把目标 MAC 地址写入帧里面发送就可。

    如果在 ARP 缓存表中没有找到相对应的IP地址,主机 A 就会在网络上发送一个广播(ARP request),目标 MAC 地址是“FF.FF.FF.FF.FF.FF”,这表示向同一网段内的所有主机发出这样的询问:“192.168.38.11 的 MAC 地址是什么?”

    网络上其他主机并不响应ARP询问,只有主机 B 接收到这个帧时,才向主机 A 做出这样的回应(ARP response):“192.168.38.11 的 MAC 地址是 00-BB-00-62-C2-02”,此回应以单播方式。这样,主机A就知道主机 B 的 MAC 地址,它就可以向主机B发送信息。同时它还更新自己的 ARP 高速缓存(ARP cache),下次再向主机B发送信息时,直接从 ARP 缓存表里查找就可。

    ARP 缓存表采用老化机制,在一段时间内如果表中的某一行没有使用,就会被删除,这样可以大大减少 ARP 缓存表的长度,加快查询速度。

    SendARP 函数
    SendARP 函数通过发送一个地址解析协议(ARP)请求,来获得与指定的目的地 IPv4 地址相对应的物理地址。

    语法格式如下:

    DWORD SendARP(
    _In_ IPAddr DestIP,
    _In_ IPAddr SrcIP,
    _Out_ PULONG pMacAddr,
    _Inout_ PULONG PhyAddrLen
    );
    1
    2
    3
    4
    5
    6
    四个参数分别是:目的 IP 地址、源 IP 地址(一般默认为 0)、物理地址缓冲区指针、以及缓冲区长度。

    获取 MAC 地址
    获取与指定的 IPv4 地址相关联的硬件或 MAC 地址:

    代码如下:

    #ifndef WIN32_LEAN_AND_MEAN
    #define WIN32_LEAN_AND_MEAN
    #endif

    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <stdio.h>
    #include <stdlib.h>

    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "ws2_32.lib")

    void usage(char *pname)
    {
    printf("Usage: %s [options] ip-address ", pname);
    printf(" -h help ");
    printf(" -l length MAC physical address length to set ");
    printf(" -s src-ip source IP address ");
    exit(1);
    }

    int __cdecl main(int argc, char **argv)
    {
    DWORD dwRetVal;
    IPAddr DestIp = 0;
    IPAddr SrcIp = 0; /* default for src ip */
    ULONG MacAddr[2]; /* for 6-byte hardware addresses */
    ULONG PhysAddrLen = 6; /* default to length of six bytes */

    char *DestIpString = NULL;
    char *SrcIpString = NULL;

    BYTE *bPhysAddr;
    unsigned int i;

    if (argc > 1) {
    for (i = 1; i < (unsigned int) argc; i++) {
    if ((argv[i][0] == '-') || (argv[i][0] == '/')) {
    switch (tolower(argv[i][1])) {
    case 'l':
    PhysAddrLen = (ULONG) atol(argv[++i]);
    break;
    case 's':
    SrcIpString = argv[++i];
    SrcIp = inet_addr(SrcIpString);
    break;
    case 'h':
    default:
    usage(argv[0]);
    break;
    } /* end switch */
    } else
    DestIpString = argv[i];
    } /* end for */
    } else
    usage(argv[0]);

    if (DestIpString == NULL || DestIpString[0] == '')
    usage(argv[0]);

    DestIp = inet_addr(DestIpString);

    memset(&MacAddr, 0xff, sizeof (MacAddr));

    printf("Sending ARP request for IP address: %s ", DestIpString);

    dwRetVal = SendARP(DestIp, SrcIp, &MacAddr, &PhysAddrLen);

    if (dwRetVal == NO_ERROR) {
    bPhysAddr = (BYTE *) & MacAddr;
    if (PhysAddrLen) {
    for (i = 0; i < (int) PhysAddrLen; i++) {
    if (i == (PhysAddrLen - 1))
    printf("%.2X ", (int) bPhysAddr[i]);
    else
    printf("%.2X-", (int) bPhysAddr[i]);
    }
    } else
    printf
    ("Warning: SendArp completed successfully, but returned length=0 ");

    } else {
    printf("Error: SendArp failed with error: %d", dwRetVal);
    switch (dwRetVal) {
    case ERROR_GEN_FAILURE:
    printf(" (ERROR_GEN_FAILURE) ");
    break;
    case ERROR_INVALID_PARAMETER:
    printf(" (ERROR_INVALID_PARAMETER) ");
    break;
    case ERROR_INVALID_USER_BUFFER:
    printf(" (ERROR_INVALID_USER_BUFFER) ");
    break;
    case ERROR_BAD_NET_NAME:
    printf(" (ERROR_GEN_FAILURE) ");
    break;
    case ERROR_BUFFER_OVERFLOW:
    printf(" (ERROR_BUFFER_OVERFLOW) ");
    break;
    case ERROR_NOT_FOUND:
    printf(" (ERROR_NOT_FOUND) ");
    break;
    default:
    printf(" ");
    break;
    }
    }

    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    更多参考
    SendARP function
    地址解析协议
    ---------------------
    作者:一去丶二三里
    来源:CSDN
    原文:https://blog.csdn.net/liang19890820/article/details/80683512
    版权声明:本文为博主原创文章,转载请附上博文链接!

  • 相关阅读:
    15天学会jQuery
    android面试题-简答题(一)
    android面试题-选择填空(一)
    【Android进阶】Android面试题目整理与讲解
    Android 面试题(有详细答案)
    Android开发人员必备的10 个开发工具
    Android环境搭建
    到底如何区分什么是架构、框架、模式和平台 ?
    c#执行Dos命令
    C#打开Word
  • 原文地址:https://www.cnblogs.com/findumars/p/10420146.html
Copyright © 2011-2022 走看看