自制Ping(3) IcmpSendEcho2Ex Demo

IP Helper 可能需要WDK支持, 我本机装了WDK, 没试过不用会怎样.

由于IcmpSendEcho2Ex()回调的形式似乎与我的WDK有所冲突, 所以这里只演示阻塞模式. Event应该不受影响.

Demo下载地址:  http://download.csdn.net/detail/ren0065/8388105

主要代码:

void CPingTest1Dlg::OnBnClickedBtnPing()
{
	// TODO:  在此添加控件通知处理程序代码
	UpdateData(TRUE);

	HANDLE h_icmp = IcmpCreateFile();
	IPAddr ip_source = inet_addr(cs_source_ip_);
	IPAddr ip_destination = inet_addr(cs_destination_ip_);
	WORD w_request_data_size = atoi(cs_request_size_);
	LPVOID p_request_data = calloc(1, w_request_data_size);
	PIP_OPTION_INFORMATION p_option_info = NULL;
	LPVOID p_reply_data = calloc(1, sizeof(ICMP_ECHO_REPLY) + 8 + w_request_data_size);
	DWORD dw_reply_data_size = sizeof(ICMP_ECHO_REPLY) + 8 + w_request_data_size;
	DWORD dw_timeout = atoi(cs_timeout_);

	DWORD dw_result = IcmpSendEcho2Ex(
		h_icmp
		, NULL
		, NULL
		, NULL
		, ip_source
		, ip_destination
		, p_request_data
		, w_request_data_size
		, p_option_info
		, p_reply_data
		, dw_reply_data_size
		, dw_timeout);

	free(p_request_data);

	cs_output_.Empty();
	if (dw_result == 0)
	{
		DWORD dw_error = GetLastError();
		CString cs_error_msg;
		switch (dw_error)
		{
		case ERROR_INVALID_PARAMETER:
			cs_error_msg = "无效参数. 当IcmpHandle是一个无效handle或ReplySize的值小于ICMP_ECHO_REPLY或ICMP_ECHO_REPLY32时会返回该错误.";
			break;
		case ERROR_IO_PENDING:
			cs_error_msg = "异步处理正在进行中.调用IcmpSendEcho2Ex异步模式成功时会返回该值, 不是错误.";
			break;
		case ERROR_NOT_ENOUGH_MEMORY:
			cs_error_msg = "内存不足";
			break;
		case ERROR_NOT_SUPPORTED:
			cs_error_msg = "不支持该请求.如果本地计算机没有IPv4协议栈将返回该错误.";
			break;
		case IP_BUF_TOO_SMALL:
			cs_error_msg = "ReplySize指定的太小.";
			break;
		default:
		{
			HLOCAL hLocal = NULL;
			DWORD dwErr = GetLastError();
			DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
			DWORD fOK = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
				NULL, dwErr, systemLocale, (LPTSTR)&hLocal, 0, NULL);
			cs_error_msg = (LPCTSTR)LocalLock(hLocal);
			break;
		}
		}
		cs_output_ = cs_error_msg;
	}
	else
	{
		CString cs_buffer;
		PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)p_reply_data;
		struct in_addr ReplyAddr;
		ReplyAddr.S_un.S_addr = pEchoReply->Address;
		cs_buffer.Format("Sent icmp message from %s to %s\r\n", cs_source_ip_, cs_destination_ip_);
		cs_output_ += cs_buffer;
		if (dw_result > 1)
		{
			cs_buffer.Format("Received %ld icmp message responses\r\n", dw_result);
			cs_output_ += cs_buffer;
			cs_buffer.Format("Information from the first response:\r\n");
			cs_output_ += cs_buffer;
		}
		else
		{
			cs_buffer.Format("Received %ld icmp message response\r\n", dw_result);
			cs_output_ += cs_buffer;
			cs_buffer.Format("Information from this response:\r\n");
			cs_output_ += cs_buffer;
		}
		cs_buffer.Format("Received from %s\r\n", inet_ntoa(ReplyAddr));
		cs_output_ += cs_buffer;
		cs_buffer.Format("Status = %ld ", pEchoReply->Status);
		cs_output_ += cs_buffer;

		if (pEchoReply->Status != IP_SUCCESS)
		{
			DWORD dw_status_err_msg_size = 1024;
			PWSTR cw_str_error = (PWSTR)calloc(1, dw_status_err_msg_size);
			GetIpErrorString(pEchoReply->Status, cw_str_error, &dw_status_err_msg_size);
			cs_output_ = WS2S(cw_str_error).c_str();
			free(cw_str_error);
		}
		else
		{
			cs_buffer.Format("(Successful)\r\n");
			cs_output_ += cs_buffer;
			cs_buffer.Format("RTT: %d\r\n", pEchoReply->RoundTripTime);
			cs_output_ += cs_buffer;
			cs_buffer.Format("SIZE: %d\r\n", pEchoReply->DataSize);
			cs_output_ += cs_buffer;
			cs_buffer.Format("TTL: %d\r\n", pEchoReply->Options.Ttl);
			cs_output_ += cs_buffer;
		}
	}

	UpdateData(FALSE);
	free(p_reply_data);
	IcmpCloseHandle(h_icmp);
}


使用IcmpSendEcho函数,您需要做以下几步: 1. 加载icmp.dll库文件。 2. 创建ICMP Echo请求数据包。 3. 打开ICMP句柄。 4. 使用IcmpSendEcho函数发送ICMP Echo请求。 5. 处理IcmpSendEcho函数返回的ICMP Echo响应数据包。 下面是一个简单的使用IcmpSendEcho函数的示例代码: ``` #include <winsock2.h> #include <iphlpapi.h> #include <icmpapi.h> #include <stdio.h> #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "ws2_32.lib") int main() { HANDLE icmpHandle = IcmpCreateFile(); if (icmpHandle == INVALID_HANDLE_VALUE) { printf("Failed to create ICMP handle.\n"); return 1; } char ipAddress[] = "www.google.com"; DWORD ipAddr = inet_addr(ipAddress); if (ipAddr == INADDR_NONE) { hostent* host = gethostbyname(ipAddress); if (host == NULL) { printf("Failed to get IP address of %s.\n", ipAddress); return 1; } ipAddr = *((DWORD*)host->h_addr); } const int bufferSize = 32; char buffer[bufferSize]; memset(buffer, 0, bufferSize); int replySize = sizeof(ICMP_ECHO_REPLY) + bufferSize; LPVOID replyBuffer = (void*)malloc(replySize); if (replyBuffer == NULL) { printf("Failed to allocate memory for reply buffer.\n"); return 1; } ICMP_ECHO_REPLY* reply = (ICMP_ECHO_REPLY*)replyBuffer; int result = IcmpSendEcho(icmpHandle, ipAddr, buffer, bufferSize, NULL, replyBuffer, replySize, 1000); if (result == 0) { printf("IcmpSendEcho failed with error: %ld\n", GetLastError()); return 1; } printf("Reply from %s: bytes=%d time=%ldms TTL=%d\n", ipAddress, reply->DataSize, reply->RoundTripTime, reply->Options.Ttl); free(replyBuffer); IcmpCloseHandle(icmpHandle); return 0; } ``` 这个示例代码会尝试向www.google.com发送ICMP Echo请求,并输出响应数据包的信息。注意,这个示例代码仅供参考,并不保证在所有环境中都能正常工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值