1

I need to write C++ code that measures the packet loss of ping - the percentage of the loss. I saw the IPHLPAPI library with lots of statistics on RTT but without packet loss.

If someone know something about it, it will be great!

Thank you.

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
user1673206
  • 1,671
  • 1
  • 23
  • 43
  • Your question needs a more clear target as to what you are actually asking. What have you done so far, what, exactly are you not sure of? – Mats Petersson Jun 04 '13 at 08:28
  • o.k. I have code that sends ping to specific IP address. in the ICMP response, there is struct with all kined of parameters such as RTT, DataSize... but i need also packet loss of that ping. I hope it is a little bit more clear. – user1673206 Jun 04 '13 at 08:51
  • I did this some time back, where I simply used a small script on top of standard ping, which counted the number of "missing" packets by the time it took to receive back the packet. But if you write your own code, you simply send out a packet, and wait for the reply to come back. If no reply within X seconds, it's a "lost" packet. (X may not be an integer here) – Mats Petersson Jun 04 '13 at 08:54

1 Answers1

1

You can use the POCO library it's small (ALOT smaller than boost) and more readable than ACE when it comes to networking.

Here's the source of a ping program using the ICMPClient You will find it under POCO_BASE/net/examples/Ping/src

#include "Poco/Util/Application.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include "Poco/Util/AbstractConfiguration.h"
#include "Poco/Net/ICMPSocket.h"
#include "Poco/Net/ICMPClient.h"
#include "Poco/Net/IPAddress.h"
#include "Poco/Net/ICMPEventArgs.h"
#include "Poco/AutoPtr.h"
#include "Poco/NumberParser.h"
#include "Poco/Delegate.h"
#include <iostream>
#include <sstream>


using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;
using Poco::Util::AbstractConfiguration;
using Poco::Net::ICMPSocket;
using Poco::Net::ICMPClient;
using Poco::Net::IPAddress;
using Poco::Net::ICMPEventArgs;
using Poco::AutoPtr;
using Poco::NumberParser;
using Poco::Delegate;


class Ping: public Application
    /// This sample demonstrates the Poco::Net::ICMPClient in conjunction with 
    /// Poco Foundation C#-like events functionality.
    ///
    /// Try Ping --help (on Unix platforms) or Ping /help (elsewhere) for
    /// more information.
{
public:
    Ping(): 
        _helpRequested(false), 
        _icmpClient(IPAddress::IPv4),
        _repetitions(4), 
        _target("localhost")
    {
    }

protected:  
    void initialize(Application& self)
    {
        loadConfiguration(); // load default configuration files, if present
        Application::initialize(self);

        _icmpClient.pingBegin += Delegate<Ping, ICMPEventArgs>(this, &Ping::onBegin);
        _icmpClient.pingReply += Delegate<Ping, ICMPEventArgs>(this, &Ping::onReply);
        _icmpClient.pingError += Delegate<Ping, ICMPEventArgs>(this, &Ping::onError);
        _icmpClient.pingEnd   += Delegate<Ping, ICMPEventArgs>(this, &Ping::onEnd);
    }

    void uninitialize()
    {
        _icmpClient.pingBegin -= Delegate<Ping, ICMPEventArgs>(this, &Ping::onBegin);
        _icmpClient.pingReply -= Delegate<Ping, ICMPEventArgs>(this, &Ping::onReply);
        _icmpClient.pingError -= Delegate<Ping, ICMPEventArgs>(this, &Ping::onError);
        _icmpClient.pingEnd   -= Delegate<Ping, ICMPEventArgs>(this, &Ping::onEnd);

        Application::uninitialize();
    }

    void defineOptions(OptionSet& options)
    {
        Application::defineOptions(options);

        options.addOption(
            Option("help", "h", "display help information on command line arguments")
                .required(false)
                .repeatable(false));

        options.addOption(
            Option("repetitions", "r", "define the number of repetitions")
                .required(false)
                .repeatable(false)
                .argument("repetitions"));

        options.addOption(
            Option("target", "t", "define the target address")
                .required(false)
                .repeatable(false)
                .argument("target"));
    }

    void handleOption(const std::string& name, const std::string& value)
    {
        Application::handleOption(name, value);

        if (name == "help")
            _helpRequested = true;
        else if (name == "repetitions")
            _repetitions = NumberParser::parse(value);
        else if (name == "target")
            _target = value;
    }

    void displayHelp()
    {
        HelpFormatter helpFormatter(options());
        helpFormatter.setCommand(commandName());
        helpFormatter.setUsage("OPTIONS");
        helpFormatter.setHeader(
            "A sample application that demonstrates the functionality of the "
            "Poco::Net::ICMPClient class in conjunction with Poco::Events package functionality.");
        helpFormatter.format(std::cout);
    }


    int main(const std::vector<std::string>& args)
    {
        if (_helpRequested) 
            displayHelp();
        else 
            _icmpClient.ping(_target, _repetitions);

        return Application::EXIT_OK;
    }


    void onBegin(const void* pSender, ICMPEventArgs& args)
    {
        std::ostringstream os;
        os << "Pinging " << args.hostName() << " [" << args.hostAddress() << "] with " << args.dataSize() << " bytes of data:" 
           << std::endl << "---------------------------------------------" << std::endl;
        logger().information(os.str());
    }

    void onReply(const void* pSender, ICMPEventArgs& args)
    {
        std::ostringstream os;
        os << "Reply from " << args.hostAddress()
           << " bytes=" << args.dataSize() 
           << " time=" << args.replyTime() << "ms"
           << " TTL=" << args.ttl();
        logger().information(os.str());
    }

    void onError(const void* pSender, ICMPEventArgs& args)
    {
        std::ostringstream os;
        os << args.error();
        logger().information(os.str());
    }

    void onEnd(const void* pSender, ICMPEventArgs& args)
    {
        std::ostringstream os;
        os << std::endl << "--- Ping statistics for " << args.hostName() << " ---"
           << std::endl << "Packets: Sent=" << args.sent() << ", Received=" << args.received()
           << " Lost=" << args.repetitions() - args.received() << " (" << 100.0 - args.percent() << "% loss),"
           << std::endl << "Approximate round trip times in milliseconds: " << std::endl
           << "Minimum=" << args.minRTT() << "ms, Maximum=" << args.maxRTT()  
           << "ms, Average=" << args.avgRTT() << "ms" 
           << std::endl << "------------------------------------------";
        logger().information(os.str());
    }

private:
    bool        _helpRequested;
    ICMPClient  _icmpClient;
    int         _repetitions;
    std::string _target;
};


int main(int argc, char** argv)
{
    AutoPtr<Ping> pApp = new Ping;
    try
    {
        pApp->init(argc, argv);
    }
    catch (Poco::Exception& exc)
    {
        pApp->logger().log(exc);
        return Application::EXIT_CONFIG;
    }
    return pApp->run();
}

You can delete the logger / help stuff to make the source a bit shorter and use OnReply / OnError / OnEnd to calculate the packet loss

You send 4 packets .... 3 packets were returned (OnReply) packet loss = 1-3/4 = 25%.

gifnoc-gkp
  • 1,506
  • 1
  • 8
  • 17
  • Thank you! i will try it. where is the POCO_BASE library? is it already on my computer? do i need to download it? – user1673206 Jun 04 '13 at 09:16