Get the ping from a remote target with Qt (Windows/Linux)
Asked Answered
A

4

12

Currently I use this code for retrieving the ping of a target system. However it works so far only under linux and it is likely dependent on the locale settings. To add support for windows will be likely even more complicated. Is there an easy way or library to get the ping of a target system? I mainly work with Qt, so it would be ideal if I could work with QSockets.

#ifndef _WIN32
QProcess ping;
ping.start("ping", QStringList() << "-c 1" << m_sHostName);
if(ping.waitForFinished(250) ) {
    while(ping.canReadLine()) {
        QString line = ping.readLine();
        if(line.contains("time=")) {
            int iStart = line.indexOf("time=") + 5;
            int iStop = line.indexOf(" ms");
            QStringRef latency(&line, iStart, iStop-iStart);

            m_vNetwork_s.append(time_s);
            m_vLatency_ms.append(QString(latency.toLocal8Bit()).toDouble());
            break;
        }
    }
}
#endif
Antisepsis answered 8/4, 2014 at 11:6 Comment(1)
Regarding ICMP with Qt, I found this link: lists.qt-project.org/pipermail/interest/2013-January/… Looks like you can't do it with Qt's network classesAdamandeve
I
3

You would need write your code for this without QAbstractSocket. In short, this base class was not designed for this use case.

The reason is that you would need to use raw sockets and run as root; that is also why you usually see the setuid flag set on the ping executable on Linux.

ICMP is "connectionless", and as such the Qt class is not feasible for it as it does not provide sending data to a specific host, etc.

You can read the more thorough explanation in here.

Insectarium answered 8/4, 2014 at 19:42 Comment(0)
C
16

You can ping on both Windows and Linux using this:

   QStringList parameters;
#if defined(WIN32)
   parameters << "-n" << "1";
#else
   parameters << "-c 1";
#endif

   parameters << m_sHostName;

   int exitCode = QProcess::execute("ping", parameters);
   if (exitCode==0) {
       // it's alive
   } else {
       // it's dead
   }
Coincidence answered 8/4, 2014 at 12:29 Comment(7)
The problem on this approach is, that I would have to define a parser for the command line output for every language of the host system. Additionally there is an overhead with this method and it could lock (for which reasons ever). I personally hate this method so much! On the other hand I was not willing to implement such a ping pong method myself, because theoretically there should be already solutions on most systems.Antisepsis
The mentioned code only returns an exit code so you don't need to parse output. Also it can be put on a thread to avoid locking.Coincidence
But you need to parse the * ms anyway if you want to plot the ping in ms. The exit status is not the delay in ms..Antisepsis
Yeah the above code only defines the accessibility of a remote target. If you need the output of ping you are right. I think there is no better way to do it.Coincidence
This code doesnt work for me! It always return 1! (but the host is definitely reachable)Ranitta
@Ranitta It did the same for me (on Windows). It worked only if I put the "-n" and "1" in seperately as an extra parameter. int exitCode = QProcess::execute("ping", QStringList() << "-n" << "1"<< m_sHostName);Mccabe
For Busibox (embedded Linux) you should also pull apart the params like you did for Windows: #if defined(WIN32) parameters << "-n" << "1"; #else parameters << "-c" << "1"; #endif ... Octal
F
8

Nejat's code didn't work for me neither. Maybe it's Windows specific (tested on Windows 7 x64 + Qt 5.6). Ping command seems to distinct parameters and values and needs them to be passed apart when creating QProcess.

So instead of passing "-n 1" in one go, you'll need to pass "-n" and "1" separately.

Basically, with Nejat's code it would be:

int exitCode = QProcess::execute("ping", QStringList()
                                     << "-n" << "1"
                                     << m_sHostName);
if (exitCode==0) {
    // it's alive
} else {
    // it's dead
}

Tested and working now.

Foment answered 28/6, 2016 at 22:21 Comment(1)
It's "-c" on linux, FYI.Instrumentalist
I
3

You would need write your code for this without QAbstractSocket. In short, this base class was not designed for this use case.

The reason is that you would need to use raw sockets and run as root; that is also why you usually see the setuid flag set on the ping executable on Linux.

ICMP is "connectionless", and as such the Qt class is not feasible for it as it does not provide sending data to a specific host, etc.

You can read the more thorough explanation in here.

Insectarium answered 8/4, 2014 at 19:42 Comment(0)
E
2

The ping method return a 0 exit code event if the target is unreachable in Windows. You have to parse the command output. The following example is working on Windows and linux :

class MyClass {
  private slots:
   void OnPing();
   void OnPingEnded();
  private:
   Process mPingProcess;
};

void MyClass::OnPing()
{
   connect(&mPingProcess, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(OnPingEnded()));
#ifdef __linux__
   mPingProcess.start("ping", QStringList() << "-c" << "1" << ui->ip->text());
#else
   mPingProcess.start("ping", QStringList() << "-n" << "1" << ui->ip->text());
#endif
}

void MyClass::OnPingEnded()
{
    QByteArray output = mPingProcess.readAllStandardOutput();
    if (!output.isEmpty())
    {
        qDebug() << output;
        if (-1 != QString(output).indexOf("ttl", 0, Qt::CaseInsensitive))
        {
           qDebug() << "PING OK";
        }
        else
        {
           qDebug() << "PING KO";
        }
    }
}
Evangelistic answered 6/4, 2018 at 12:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.