icmpSendEcho2 函数 (icmpapi.h)

IcmpSendEcho2 函数发送 IPv4 ICMP 回显请求,如果 EventApcRoutine) 非 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 响应到达时,最多) (一次发出信号的事件。 如果指定此参数,则它需要有效事件对象的句柄。 使用 CreateEventCreateEventEx 函数创建此事件对象。

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

[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 获取返回错误的消息字符串。

注解

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

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

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

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

如果同时指定 了 EventApcRoutine 参数,则在 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,请使用 Icmp6CreateFileIcmp6SendEcho2Icmp6ParseReplies 函数。

头文件的 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

另请参阅