IcmpSendEcho返回183

时间:2014-10-25 01:33:44

标签: c++ windows winsock ping winsock2

我在MSDN here中修改了此代码示例。如果我单独构建它,它工作正常,但如果我将它添加到我的应用程序,它会失败。为方便起见,我包括了我所拥有的课程的精确改编。

我只想每秒做一次简单的ping。原始套接字无法在没有管理员权限的情况下工作,而且这种ICMP.dll方法在我的应用程序中不起作用,我不明白为什么。错误183沿着"不能创建文件,因为它已经存在"在这种背景下没有任何意义。

有人能发现问题吗?非常感谢你的帮助。

Ping.h

    #pragma once
    #include "Ping.h"
    #include "LogBase.h"
    class WinPing :
        public Ping
    {
    public:
        WinPing(char* address, int period);
        ~WinPing();

        unsigned long           GetRTT();
    private:
        HANDLE                  _hIcmpFile;
        unsigned long           _ipaddr;
        DWORD                   _dwRetVal;
        LPVOID                  _replyBuffer;
        DWORD                   _replySize;

        static HANDLE           _inputTimer;


        int                     _period;
        unsigned long           _lastRTT;



        static DWORD WINAPI     AsyncPingHandler(void* Param);
        void                    DoPing();   

    };

WinPing.h

    #pragma once
    #include "Ping.h"
    #include "LogBase.h"
    class WinPing :
        public Ping
    {
    public:
        WinPing(char* address, int period);
        ~WinPing();

        unsigned long           GetRTT();
    private:
        HANDLE                  _hIcmpFile;
        unsigned long           _ipaddr;
        DWORD                   _dwRetVal;
        LPVOID                  _replyBuffer;
        DWORD                   _replySize;

        static HANDLE           _inputTimer;


        int                     _period;
        unsigned long           _lastRTT;



        static DWORD WINAPI     AsyncPingHandler(void* Param);
        void                    DoPing();   

    };

WinPing.cpp

    #include "WinPing.h"
    #include <winsock2.h>
    #include <iphlpapi.h>
    #include <icmpapi.h>
    #include <stdio.h>
    #include "utils.h"

    #pragma comment(lib, "iphlpapi.lib")
    #pragma comment(lib, "ws2_32.lib")

    HANDLE WinPing::_inputTimer = NULL;
    char SendData[32] = "Data Buffer";

    unsigned long WinPing::GetRTT()
    {
        return _lastRTT;
    }


    void WinPing::DoPing()
    {
        LARGE_INTEGER t;
        t.HighPart = t.LowPart = 0;
        SetWaitableTimer(_inputTimer, &t, _period, NULL, NULL, TRUE);

        while (true)
        {
            int r = WaitForSingleObject(_inputTimer, _period * 2);
            if (r != WAIT_OBJECT_0)
            {
                LogLog("InputHandler: Bad Timer return", LogError);
            }

            _dwRetVal = IcmpSendEcho(_hIcmpFile, _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;
                LogLog("\tSent icmp message to %s\n", LogDebug, _address);
                if (_dwRetVal > 1) {
                    LogLog("\tReceived %ld icmp message responses\n", LogDebug, _dwRetVal);
                    LogLog("\tInformation from the first response:\n", LogDebug);
                }
                else {
                    LogLog("\tReceived %ld icmp message response\n", LogDebug, _dwRetVal);
                    LogLog("\tInformation from this response:\n", LogDebug);
                }
                LogLog("\t  Received from %s\n", LogDebug, inet_ntoa(ReplyAddr));
                LogLog("\t  Status = %ld\n", LogDebug,
                    pEchoReply->Status);
                LogLog("\t  Roundtrip time = %ld milliseconds\n", LogDebug,
                    pEchoReply->RoundTripTime);

                //needs synchronization here. Probably not very important
                _lastRTT = pEchoReply->RoundTripTime;
                LogLog("\t  Roundtrip time = %ld milliseconds\n", LogDebug, _lastRTT);
                IcmpCloseHandle(_hIcmpFile);
            }
            else {
                LogLog("\tCall to IcmpSendEcho failed.\n", LogError);
                LogLog("\tIcmpSendEcho returned error: %ld\n", LogError, GetLastError());

            }

        }
    }

    DWORD WINAPI WinPing::AsyncPingHandler(void* Param)
    {
        _inputTimer = CreateWaitableTimer(NULL, false, NULL);
        if (!_inputTimer)
        {
            LogLog("Unable to create input waitable timer", LogError);
            return 1;
        }

        LogLog("RTT Ping Thread started", LogDebug);
        WinPing* This = (WinPing*)Param;
        This->DoPing();

        return 0;

    }


    WinPing::WinPing(char* address, int period)
        :Ping(address),
        _period(period)
    {
        // Declare and initialize variables
        _ipaddr = INADDR_NONE;
        _dwRetVal = 0;
        _replyBuffer = NULL;
        _replySize = 0;


        _ipaddr = inet_addr(address);
        if (_ipaddr == INADDR_NONE) {
            LogLog("Not an IP Address:%s", LogError, address);
            return;
        }

        _hIcmpFile = IcmpCreateFile();
        if (_hIcmpFile == INVALID_HANDLE_VALUE) {
            LogLog("\tUnable to open handle.\n", LogError);
            LogLog("IcmpCreatefile returned error: %ld\n", LogError, GetLastError());
            return;
        }

        _replySize = sizeof(ICMP_ECHO_REPLY) + sizeof(SendData);
        _replyBuffer = (VOID*)malloc(_replySize);
        if (_replyBuffer == NULL) {
            LogLog("\tUnable to allocate memory\n", LogError);
            return;
        }

        //Spawn thread on AsyncPingHandler()
        CreateClassThread(AsyncPingHandler, this);

    }


    WinPing::~WinPing()
    {
    }

2 个答案:

答案 0 :(得分:1)

GetLastError()失败后,您没有立即致电IcmpSendEcho() (调用IcmpCreateFile()时也是如此)。您首先调用LogLog(),这可能会更改GetLastError()返回的错误代码,例如,如果它正在记录到无法找到的文件。 始终在执行可能调用系统函数的任何操作之前调用GetLastError()

else {
    DWORD dwErrCode = GetLastError(); // <-- call GetLastError() first
    LogLog("\tCall to IcmpSendEcho failed.\n", LogError);
    LogLog("\tIcmpSendEcho returned error: %u\n", LogError, dwErrCode); // <-- then use the value when needed
    return;
}

答案 1 :(得分:1)

我发现使用GetRTTandHopCount更简单,更稳定的ping方式。这是一个例子。

UINT ip = inet_addr(serverAddress);
ULONG hopCount = 0;
ULONG RTT = 0;

if (GetRTTAndHopCount(ip, &hopCount, 30, &RTT) == TRUE) {
    printf("Hops: %ld\n", hopCount);
    printf("RTT: %ld\n", RTT);
}
else {
    printf("Error: %ld\n", GetLastError());
}

return RTT;
相关问题