ping程序,在底层使用的ICMP协议,可通过API接口IcmpSendEcho实现
实现需要支持域名主机和IP地址主机,所以首先使用gethostbyname取到主机的地址,然后启动消息处理线程,启动定时器
处理,在定时器处理函数中调用IcmpSendEcho,即实现了定时ping
详细参考代码:
// ping_test.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <conio.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <icmpapi.h>
#pragma comment(lib,"Ws2_32.lib")
#pragma comment(lib,"Iphlpapi.lib")
UINT cnt = 0;
// 定时器回调函数
void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime);
// 线程回调函数
DWORD CALLBACK ThreadProc(PVOID pvoid);
// Declare and initialize variables
int i;
HANDLE hIcmpFile;
unsigned long ipaddr = INADDR_NONE;
DWORD dwRetVal = 0;
char SendData[160] = "Data Buffer";
LPVOID ReplyBuffer = NULL;
DWORD ReplySize = 0;
char** pargv = NULL;
int interval = 200; //200ms
int block_size = 135; //包大小
char *hostname = "www.baidu.com";
int main(int argc, char* argv[])
{
WSADATA Ws;
//Init Windows Socket
if (WSAStartup(MAKEWORD(2, 2), &Ws) != 0)
{
return -1;
}
// Validate the parameters
if (argc < 2) {
printf("usage: %s HOST INTERVAL BLOCK_SIZE\n", argv[0]);
return 1;
}
else
{
hostname = argv[1];
printf("主机: %s \n", argv[1]);
}
if (argc >= 3)
{
interval = atoi(argv[2]);
printf("间隔: %s \n", argv[2]);
if (argc > 3)
{
block_size = atoi(argv[3]);
printf("帧大小: %s \n", argv[3]);
}
}
pargv = argv;
struct hostent* host = gethostbyname(hostname);
if (host == NULL)
{
printf("获取主机地址失败!\n");
return 1;
}
memcpy(&ipaddr, &(host->h_addr_list[0]), sizeof(struct in_addr));
if (ipaddr == INADDR_NONE) {
printf("输入有效主机地址\n");
return 1;
}
hIcmpFile = IcmpCreateFile();
if (hIcmpFile == INVALID_HANDLE_VALUE) {
printf("\tUnable to open handle.\n");
printf("IcmpCreatefile returned error: %ld\n", GetLastError());
return 1;
}
ReplySize = sizeof(ICMP_ECHO_REPLY) + block_size;
ReplyBuffer = (VOID*)malloc(ReplySize);
if (ReplyBuffer == NULL) {
printf("\tUnable to allocate memory\n");
return 1;
}
DWORD dwThreadId;
// 创建线程
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, 0, 0, &dwThreadId);
printf("hello, thread start!\n");
//Wait for press any key to exit...
_getch();
return 0;
}
//定时器处理函数
void CALLBACK TimeProc(HWND hwnd, UINT message, UINT idTimer, DWORD dwTime)
{
dwRetVal = IcmpSendEcho(hIcmpFile, ipaddr, SendData, block_size,
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", pargv[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\n",
pEchoReply->Status);
printf("\t Roundtrip time = %ld milliseconds\n",
pEchoReply->RoundTripTime);
printf("\t data = %s\n", pEchoReply->Data);
}
else {
printf("\tIcmpSendEcho returned error: %ld\n", GetLastError());//出错之后,必须马上调用这个函数才能出现返回错误。
printf("\tCall to IcmpSendEcho failed.\n");
return ;
}
cnt++;
printf("ping count = %d\n", cnt);
}
//线程函数,用于实现消息分发,启动定时器
DWORD CALLBACK ThreadProc(PVOID pvoid)
{
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
SetTimer(NULL, 10, interval, TimeProc);
while (GetMessage(&msg, NULL, 0, 0))
{
if (msg.message == WM_TIMER)
{
TranslateMessage(&msg); // 翻译消息
DispatchMessage(&msg); // 分发消息
}
}
KillTimer(NULL, 10);
return 0;
}
网友评论