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 |