美文网首页
使用WIN32 API实现定时PING

使用WIN32 API实现定时PING

作者: LittleFat | 来源:发表于2015-11-05 12:59 被阅读888次

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;
}

相关文章

网友评论

      本文标题:使用WIN32 API实现定时PING

      本文链接:https://www.haomeiwen.com/subject/ilqchttx.html