icmpSendEcho2 函数 (icmpapi.h)

IcmpSendEcho2 函数发送 IPv4 ICMP 回显请求,如果 Event 或 ApcRoutine) 非 NULL,则立即返回 (,或者在指定的超时后返回 。ReplyBuffer 包含 ICMP 回显响应(如果有)。

语法

IPHLPAPI_DLL_LINKAGE DWORD IcmpSendEcho2(
  [in]           HANDLE                 IcmpHandle,
  [in, optional] HANDLE                 Event,
  [in, optional] PIO_APC_ROUTINE        ApcRoutine,
  [in, optional] PVOID                  ApcContext,
  [in]           IPAddr                 DestinationAddress,
  [in]           LPVOID                 RequestData,
  [in]           WORD                   RequestSize,
  [in, optional] PIP_OPTION_INFORMATION RequestOptions,
  [out]          LPVOID                 ReplyBuffer,
  [in]           DWORD                  ReplySize,
  [in]           DWORD                  Timeout
);

参数

[in] IcmpHandle

ICMPCreateFile 函数返回的打开句柄。

[in, optional] Event

ICMP 响应到达时,最多) (一次发出信号的事件。 如果指定此参数,则它需要有效事件对象的句柄。 使用 CreateEvent 或 CreateEventEx 函数创建此事件对象。

有关使用事件的详细信息,请参阅 事件对象。

[in, optional] ApcRoutine

当调用线程处于可警报线程中并且 ICMPv4 回复到达时调用的例程。 必须定义PIO_APC_ROUTINE_DEFINED,才能强制此参数的数据类型PIO_APC_ROUTINE而不是 FARPROC。

[in, optional] ApcContext

传递给 ApcRoutine 参数中指定的回调例程的可选参数最多 (一次,) ICMP 响应到达或发生错误时。

[in] DestinationAddress

回显请求的 IPv4 目标,采用 IPAddr 结构的形式。

[in] RequestData

指向缓冲区的指针,该缓冲区包含要发送的请求中的数据。

[in] RequestSize

RequestData 参数指向的请求数据缓冲区的大小(以字节为单位)。

[in, optional] RequestOptions

指向请求的 IP 标头选项的指针,采用 IP_OPTION_INFORMATION 结构的形式。

如果不需要指定 IP 标头选项,此参数可能为 NULL 。

[out] ReplyBuffer

指向缓冲区的指针,用于保存对请求的任何答复。 返回时,缓冲区包含 ICMP_ECHO_REPLY 结构数组,后跟选项和数据。

缓冲区必须足够大,以容纳至少一个 ICMP_ECHO_REPLY 结构,加上 RequestSize 字节的数据,以及额外的 8 字节数据 (ICMP 错误消息) 的大小。

[in] ReplySize

回复缓冲区的分配大小(以字节为单位)。

缓冲区必须足够大,以容纳至少一个 ICMP_ECHO_REPLY 结构,加上 RequestSize 字节的数据,以及额外的 8 字节数据 (ICMP 错误消息) 的大小。

[in] Timeout

等待答复的时间(以毫秒为单位)。

返回值

同步调用时, IcmpSendEcho2 函数返回 在 ReplyBuffer 中接收和存储的答复数。 如果返回值为零,则对于扩展错误信息,请调用 GetLastError。

异步调用时, IcmpSendEcho2 函数返回零。 对 GetLastError 的后续调用ERROR_IO_PENDING返回 扩展错误代码, 以指示操作正在进行中。 当 Event 参数中指定的 事件发出信号或调用 ApcRoutine 参数中的回调函数时,可以稍后检索结果。

如果返回值为零,则对于扩展错误信息,请调用 GetLastError。

如果函数失败,则 GetLastError 返回的扩展错误代码可以是以下值之一。

返回代码 说明
ERROR_INVALID_PARAMETER 向该函数传递了无效参数。 如果 IcmpHandle 参数包含无效句柄,则返回此错误。 如果 ReplySize 参数指定的值小于 ICMP_ECHO_REPLY 结构的大小,也可能会返回此错误。
ERROR_IO_PENDING 操作正在进行中。 此值由成功异步调用 IcmpSendEcho2 返回,并不表示出现错误。
ERROR_NOT_ENOUGH_MEMORY 没有足够的可用内存来完成该操作。
ERROR_NOT_SUPPORTED 不支持该请求。 如果本地计算机上没有 IPv4 堆栈,则返回此错误。
IP_BUF_TOO_SMALL 在 ReplySize 参数中指定的 ReplyBuffer 的大小太小。
其他 使用 FormatMessage 获取返回错误的消息字符串。

注解

如果 ApcRoutine 或 Event 参数为 NULL,则同步调用 IcmpSendEcho2 函数。 以同步方式调用时,返回值包含等待 Timeout 参数中指定的时间后在 ReplyBuffer 中接收和存储的答复数。 如果返回值为零,则对于扩展错误信息,请调用 GetLastError。

指定 ApcRoutine 或 Event 参数时,将异步调用 IcmpSendEcho2 函数。 异步调用时, 需要 ReplyBuffer 和 ReplySize 参数才能接受响应。 ICMP 响应数据复制到提供的 ReplyBuffer 中,当) 指定 Event 参数或 (指定 ApcRoutine 参数时调用回调函数时,应用程序) (发出信号。 应用程序必须使用 IcmpParseReplies 函数分析 ReplyBuffer 参数指向的数据。

如果指定了 Event 参数,则异步调用 IcmpSendEcho2 函数。 当 ICMP 响应到达时,Event 参数中指定的 事件 最多 (一次) 发出信号。 使用 CreateEvent 或 CreateEventEx 函数创建此事件对象。

如果指定 了 ApcRoutine 参数,则异步调用 IcmpSendEcho2 函数。 ApcRoutine 参数应指向用户定义的回调函数。 当 ICMP 响应到达时, ApcRoutine 参数中指定的回调函数最多 (调用一次) 。 对 ApcRoutine 参数中指定的回调函数的调用进行序列化。

如果同时指定 了 Event 和 ApcRoutine 参数,则在 ICMP 响应到达时, Event 参数中指定的事件最多 () 一次,但 忽略 ApcRoutine 参数中指定的回调函数。

任何使用 ApcRoutine 参数异步调用 IcmpSendEcho2 函数的应用程序都必须定义PIO_APC_ROUTINE_DEFINED,以强制 ApcRoutine 参数的数据类型PIO_APC_ROUTINE而不是 FARPROC。

注意

必须先定义PIO_APC_ROUTINE_DEFINED ,然后才能包含 Icmpapi.h 头文件。

必须使用以下语法将 ApcRoutine 指向的回调函数定义为 VOID 类型的函数:

typedef
VOID WINAPI
(*PIO_APC_ROUTINE) (
    IN PVOID ApcContext,
    IN PIO_STATUS_BLOCK IoStatusBlock,
    IN ULONG Reserved
    );

传递给回调函数的参数包括:

参数 说明
IN PVOID ApcContext 传递给 IcmpSendEcho2 函数的 AppContext 参数。 应用程序可以使用此参数来标识回调函数正在响应的 IcmpSendEcho2 请求。
IN PIO_STATUS_BLOCK IoStatusBlock 指向 IO_STATUS_BLOCK的指针。 此变量包含最终完成状态和有关操作的信息。 在回复中实际收到的字节数在IO_STATUS_BLOCK结构的 Information 成员中返回。

IO_STATUS_BLOCK结构在Wdm.h头文件中定义。
在 ULONG 保留 此参数为保留参数。

ApcRoutine 参数中指定的回调函数必须在调用 IcmpSendEcho2 函数的应用程序所在的同一进程中实现。 如果回调函数位于单独的 DLL 中,则应在调用 IcmpSendEcho2 函数之前加载 DLL。

IcmpSendEcho2 函数是从 导出的Iphlpapi.dll。

对于 IPv6,请使用 Icmp6CreateFile、 Icmp6SendEcho2 和 Icmp6ParseReplies 函数。

头文件的 include 指令必须放在头文件的 include 指令 Iphlpapi.h 之前 Icmpapi.h 。

示例

以下示例同步调用 IcmpSendEcho2 函数。 该示例将 ICMP 回送请求发送到命令行中指定的 IP 地址,并输出从第一个响应接收的信息。

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

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

int __cdecl main(int argc, char **argv)
{
    // Declare and initialize variables.
    HANDLE hIcmpFile;
    unsigned long ipaddr = INADDR_NONE;
    DWORD dwRetVal = 0;
    DWORD dwError = 0;
    char SendData[] = "Data Buffer";
    LPVOID ReplyBuffer = NULL;
    DWORD ReplySize = 0;

    // Validate the parameters.
    if (argc != 2) {
        printf("usage: %s IP address\n", argv[0]);
        return 1;
    }

    ipaddr = inet_addr(argv[1]);
    if (ipaddr == INADDR_NONE) {
        printf("usage: %s IP address\n", argv[0]);
        return 1;
    }

    hIcmpFile = IcmpCreateFile();
    if (hIcmpFile == INVALID_HANDLE_VALUE) {
        printf("\tUnable to open handle.\n");
        printf("IcmpCreatefile returned error: %ld\n", GetLastError());
        return 1;
    }

    // Allocate space for a single reply.
    ReplySize = sizeof (ICMP_ECHO_REPLY) + sizeof (SendData) + 8;
    ReplyBuffer = (VOID *) malloc(ReplySize);
    if (ReplyBuffer == NULL) {
        printf("\tUnable to allocate memory for reply buffer\n");
        return 1;
    }

    dwRetVal = IcmpSendEcho2(hIcmpFile, NULL, NULL, NULL,
                             ipaddr, SendData, sizeof (SendData), NULL,
                             ReplyBuffer, ReplySize, 1000);
    if (dwRetVal != 0) {
        PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY) ReplyBuffer;
        struct in_addr ReplyAddr;
        ReplyAddr.S_un.S_addr = pEchoReply->Address;
        printf("\tSent icmp message to %s\n", argv[1]);
        if (dwRetVal > 1) {
            printf("\tReceived %ld icmp message responses\n", dwRetVal);
            printf("\tInformation from the first response:\n");
        } else {
            printf("\tReceived %ld icmp message response\n", dwRetVal);
            printf("\tInformation from this response:\n");
        }
        printf("\t  Received from %s\n", inet_ntoa(ReplyAddr));
        printf("\t  Status = %ld  ", pEchoReply->Status);
        switch (pEchoReply->Status) {
        case IP_DEST_HOST_UNREACHABLE:
            printf("(Destination host was unreachable)\n");
            break;
        case IP_DEST_NET_UNREACHABLE:
            printf("(Destination Network was unreachable)\n");
            break;
        case IP_REQ_TIMED_OUT:
            printf("(Request timed out)\n");
            break;
        default:
            printf("\n");
            break;
        }

        printf("\t  Roundtrip time = %ld milliseconds\n",
               pEchoReply->RoundTripTime);
    } else {
        printf("Call to IcmpSendEcho2 failed.\n");
        dwError = GetLastError();
        switch (dwError) {
        case IP_BUF_TOO_SMALL:
            printf("\tReplyBufferSize too small\n");
            break;
        case IP_REQ_TIMED_OUT:
            printf("\tRequest timed out\n");
            break;
        default:
            printf("\tExtended error returned: %ld\n", dwError);
            break;
        }
        return 1;
    }
    return 0;
}

要求

要求 值
最低受支持的客户端 Windows 2000 专业版 [桌面应用 |UWP 应用]
最低受支持的服务器 Windows 2000 Server [桌面应用 |UWP 应用]
目标平台 Windows
标头 icmpapi.h
Library Iphlpapi.lib
DLL Windows Server 2008、Windows Vista、Windows Server 2003 和 Windows XP 上的 Iphlpapi.dll;Windows 2000 Server 和 Windows 2000 专业版上的 Icmp.dll

另请参阅