sendARP 函数 (iphlpapi.h)

SendARP 函数 (ARP) 请求发送地址解析协议,以获取与指定目标 IPv4 地址对应的物理地址。

语法

IPHLPAPI_DLL_LINKAGE DWORD SendARP(
  [in]      IPAddr DestIP,
  [in]      IPAddr SrcIP,
  [out]     PVOID  pMacAddr,
  [in, out] PULONG PhyAddrLen
);

参数

[in] DestIP

目标 IPv4 地址,采用 IPAddr 结构的形式。 ARP 请求尝试获取与此 IPv4 地址对应的物理地址。

[in] SrcIP

发送方的源 IPv4 地址,采用 IPAddr 结构的形式。 此参数是可选的,用于选择接口以针对 ARP 条目发送请求。 调用方可以指定与此参数的 INADDR_ANY IPv4 地址对应的零。

[out] pMacAddr

指向 ULONG 变量数组的指针。 此数组必须至少有两个 ULONG 元素才能保存以太网或令牌环物理地址。 此数组的前六个字节接收与 DestIP 参数指定的 IPv4 地址对应的物理地址。

[in, out] PhyAddrLen

输入时,一个指向 ULONG 值的指针,该值指定最大缓冲区大小(以字节为单位),应用程序已留出一部分来接收物理地址或 MAC 地址。 对于以太网或令牌环物理地址,缓冲区大小应至少为 6 个字节

用于接收物理地址的缓冲区由 pMacAddr 参数指向。

成功输出时,此参数指向一个值,该值指定写入 pMacAddr 指向的缓冲区的字节数。

返回值

如果函数成功,则返回值NO_ERROR。

如果函数失败,则返回值为以下错误代码之一。

返回代码 说明
ERROR_BAD_NET_NAME
找不到网络名称。 当未收到对 SendARP 请求的 ARP 答复时,将在 Windows Vista 和更高版本上返回此错误。 如果由于目标 IPv4 地址不在同一子网中或目标计算机未运行而无法访问,则会发生此错误。
ERROR_BUFFER_OVERFLOW
文件名太长。 如果 PhyAddrLen 参数指向的 ULONG 值小于 6(存储完整物理地址所需的大小),则会在 Windows Vista 上返回此错误。
ERROR_GEN_FAILURE
附加到系统的设备无法正常工作。 如果未收到对 SendARP 请求的 ARP 答复,则会在 Windows Server 2003 及更早版本上返回此错误。 如果由于目标 IPv4 地址不在同一子网中或目标计算机无法运行而无法访问,则会发生此错误。
ERROR_INVALID_PARAMETER
其中一个参数无效。 如果 pMacAddrPhyAddrLen 参数为 NULL 指针,则会在 Windows Server 2003 及更早版本上返回此错误。
ERROR_INVALID_USER_BUFFER
提供给请求操作的用户缓冲区无效。 如果 PhyAddrLen 参数指向的 ULONG 值为零,则会在 Windows Server 2003 及更早版本上返回此错误。
ERROR_NOT_FOUND
找不到元素。 如果 SrcIp 参数未在本地计算机上的接口上指定源 IPv4 地址或 INADDR_ANY IP 地址 (IPv4 地址 0.0.0.0) ,则 Windows Vista 上将返回此错误。
ERROR_NOT_SUPPORTED
在本地计算机上运行的操作系统不支持 SendARP 函数。
其他
如果函数失败,请使用 FormatMessage 获取返回错误的消息字符串。

注解

SendARP 函数用于请求物理硬件地址 (有时称为对应于指定目标 IPv4 地址的 MAC 地址) 。 如果请求的信息不在本地计算机上的 ARP 表中,则 SendARP 函数将导致发送 ARP 请求以获取物理地址。 如果函数成功,则会在 pMacAddr 参数指向的数组中返回与指定目标 IPv4 地址对应的物理地址。

仅当目标 IPv4 地址位于本地子网上时,IPv4 地址的物理地址才可用, (无需通过任何路由器) 即可直接访问该 IPv4 地址。 如果目标 IPv4 地址不在本地子网上, 则 SendARP 函数将失败。

如果 SendARP 函数在 Windows Vista 及更高版本上成功,则会使用结果更新本地计算机上的 ARP 表。 如果 SendARP 函数在 Windows Server 2003 及更早版本上成功,则本地计算机上的 ARP 表不受影响。

Windows Vista 和更高版本上的 SendARP 函数返回的错误返回值与 Windows Server 2003 及更早版本上的 SendARP 函数不同。

在 Windows Vista 及更高版本中,作为 pMacAddrPhyAddrLen 参数传递给 SendARP 函数的 NULL 指针会导致访问冲突,并且应用程序被终止。 如果 Windows Vista 及更高版本发生错误,并且ERROR_BAD_NET_NAMEERROR_BUFFER_OVERFLOWERROR_NOT_FOUND返回,则 PhyAddrLen 参数指向的 ULONG 值将设置为零。 如果在 Windows Vista 及更高版本上 PhyAddrLen 参数指向的 ULONG 值小于 6,则 SendARP 函数将返回ERROR_BUFFER_OVERFLOW指示用于接收物理地址的缓冲区太小。 如果 SrcIp 参数指定的 IPv4 地址不是本地计算机上的接口,则 Windows Vista 和更高版本上的 SendARP 函数将返回 ERROR_NOT_FOUND

在 Windows Server 2003 及更早版本中,作为 pMacAddrPhyAddrLen 参数传递给 SendARP 函数的 NULL 指针将返回ERROR_INVALID_PARAMETER。 如果在 Windows Server 2003 及更早版本上发生错误,并且返回ERROR_GEN_FAILUREERROR_INVALID_USER_BUFFER,则 PhyAddrLen 参数指向的 ULONG 值将设置为零。 如果在 Windows Server 2003 及更早版本中,PhyAddrLen 参数指向的 ULONG 值小于 6,则 SendARP 函数不会返回错误,而只返回 pMacAddr 参数指向的数组中的部分硬件地址。 因此,如果 PhyAddrLen 参数指向的值为 4,则在 pMacAddr 参数指向的数组中仅返回硬件地址的前 4 个字节。 如果 SrcIp 参数指定的 IPv4 地址不是本地计算机上的接口,则 Windows Server 2003 及更早版本上的 SendARP 函数将忽略 SrcIp 参数,并将本地计算机上的 IPv4 地址用于源 IPv4 地址。

GetIpNetTable 函数检索本地计算机上的 ARP 表,该表将 IPv4 地址映射到物理地址。

CreateIpNetEntry 函数在本地计算机上的 ARP 表中创建 ARP 条目。

DeleteIpNetEntry 函数从本地计算机上的 ARP 表中删除 ARP 条目。

SetIpNetEntry 函数修改本地计算机上 ARP 表中的现有 ARP 条目。

FlushIpNetTable 函数从本地计算机上的 ARP 表中删除指定接口的所有 ARP 条目。

在 Windows Vista 及更高版本上, ResolveIpNetEntry2 函数可用于替换 SendARP 函数。 如果传递给 ResolveIpNetEntry2 函数的 MIB_IPNET_ROW2 结构的 Address 成员是 IPv4 地址,则发送 ARP 请求。

在 Windows Vista 上,当传递给这些函数的 MIB_IPNET_ROW2 结构的 Address 成员是 IPv4 地址时,可以使用一组新的函数来访问、修改和删除 ARP 表条目。 新函数包括: GetIpNetTable2CreateIpNetEntry2DeleteIpNetEntry2FlushIpNetTable2SetIpNetEntry2

有关 IPAddr 数据类型的信息,请参阅 Windows 数据类型。 若要在点点十进制表示法和 IPAddr 格式之间转换 IP 地址,请使用 inet_addrinet_ntoa 函数。

示例

以下代码演示如何 (与指定的 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\n", pname);
    printf("\t -h \t\thelp\n");
    printf("\t -l length \tMAC physical address length to set\n");
    printf("\t -s src-ip \tsource IP address\n");
    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] == '\0')
        usage(argv[0]);

    DestIp = inet_addr(DestIpString);

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

    printf("Sending ARP request for IP address: %s\n", 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\n", (int) bPhysAddr[i]);
                else
                    printf("%.2X-", (int) bPhysAddr[i]);
            }
        } else
            printf
                ("Warning: SendArp completed successfully, but returned length=0\n");

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

    return 0;
}


要求

要求
最低受支持的客户端 Windows 2000 Professional [仅限桌面应用]
最低受支持的服务器 Windows 2000 Server [仅限桌面应用]
目标平台 Windows
标头 iphlpapi.h
Library Iphlpapi.lib
DLL Iphlpapi.dll

另请参阅

CreateIpNetEntry

CreateIpNetEntry2

CreateProxyArpEntry

DeleteIpNetEntry

DeleteIpNetEntry2

DeleteProxyArpEntry

FlushIpNetTable

FlushIpNetTable2

GetIpNetEntry2

GetIpNetTable2

IP 帮助程序函数参考

IP 帮助程序起始页

IPAddr

ResolveIpNetEntry2

SetIpNetEntry

SetIpNetEntry2