본문 바로가기
놀기/Qt

QT에서 Ping 명령어 실행하기

by Hi~ 2023. 9. 24.

ping을 구현하는 것도 방법이지만 ping 프로그램을 실행하여 결과를 사용하는 것도 좋은 방법이다.

이번에는 인터넷에서 쉽게 구할 수 있는 샘플을 사용하여 ping 명령어 실행해보려 한다.

 

목표는 ping을 실행하고 ping의 시간을 표시하는 것을 목표로 한다.

 

참조할 코드가 있으면 좋으니 아래 2개를 인터넷 검색으로 찾아 사용했다.

 

https://github.com/edhana/qt-ping-example

 

GitHub - edhana/qt-ping-example: Example of a ping command (unix) using the QProcess class from QT Framework

Example of a ping command (unix) using the QProcess class from QT Framework - GitHub - edhana/qt-ping-example: Example of a ping command (unix) using the QProcess class from QT Framework

github.com

 

받아 실행하면 Qt 버전에 따라 다르겠지만, sleep() 함수 부분에서 문제가 생겨 수정했다.

 

2022.08.01 - [일하기/Qt] - warning: '_sleep' is deprecated

 

warning: '_sleep' is deprecated

Qt에서 sleep() 함수를 사용하면 아래와 같이 에러가 난다. warning: '_sleep' is deprecated: This function or variable has been superceded by newer library or operating system functionality. Consider u..

busyman.tistory.com

 

수정 후, 실행하면 아래와 같이 문제없이 돌아간다. 한글 때문에 아래와 같이 나오는데 그냥 넘어간다.

Iniciando o ping ...
read on ...
Acabou!!!
LENDO:  "\r\n"
Acabou!!!
LENDO:  "Ping www.google.com [172.217.161.68] 32\xB9\xD9\xC0\xCC\xC6\xAE \xB5\xA5\xC0\xCC\xC5\xCD \xBB\xE7\xBF\xEB:\r\n"
Acabou!!!
LENDO:  "\xBF\xE4\xC3\xBB \xBD\xC3\xB0\xA3\xC0\xCC \xB8\xB8\xB7\xE1\xB5\xC7\xBE\xFA\xBD\xC0\xB4\xCF\xB4\xD9.\r\n"
Acabou!!!
LENDO:  "172.217.161.68\xC0\xC7 \xC0\xC0\xB4\xE4: \xB9\xD9\xC0\xCC\xC6\xAE=32 \xBD\xC3\xB0\xA3=65ms TTL=112\r\n"
Acabou!!!
LENDO:  "172.217.161.68\xC0\xC7 \xC0\xC0\xB4\xE4: \xB9\xD9\xC0\xCC\xC6\xAE=32 \xBD\xC3\xB0\xA3=64ms TTL=112\r\n"
Terminou o processo.
19:22:32: Debugging of E:\busyman\Qt\build-PingTeste-Desktop_Qt_5_12_12_MinGW_32_bit-Debug\debug\PingTeste.exe has finished with exit code 1.

 

2) QPing

https://github.com/JayTwoLab/QPing

 

GitHub - JayTwoLab/QPing: Ping class for Qt 5 or 6 (without user elevation) Qt 5 또는 6 기반 계정 상승 필요없는 핑

Ping class for Qt 5 or 6 (without user elevation) :kr: Qt 5 또는 6 기반 계정 상승 필요없는 핑 - GitHub - JayTwoLab/QPing: Ping class for Qt 5 or 6 (without user elevation) Qt 5 또는 6 기반 계정 상승 필요없는 핑

github.com

QPing은 컴파일에 문제가 없지만 MinGW로 빌드하여 실행하면 문제가 있는 듯하다. 개발 환경에 따라 나타날 수 있는 문제이니 그냥 넘어가자.

 

 

bmPingTest 만들기


OS별로 ping command의 출력 결과는 다양하다.

 

----------------
Ubuntu
----------------

$ ping www.google.com
PING www.google.com (142.250.207.100) 56(84) bytes of data.
64 bytes from kix06s11-in-f4.1e100.net (142.250.207.100): icmp_seq=1 ttl=110 time=44.8 ms

$ ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.099 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.098 ms

$ ping www.naver.com
PING www.naver.com.nheos.com (223.130.195.95) 56(84) bytes of data.


----------------
Windows
----------------

> ping 127.0.0.1
Ping 127.0.0.1 32바이트 데이터 사용:
127.0.0.1의 응답: 바이트=32 시간<1ms TTL=128
127.0.0.1의 응답: 바이트=32 시간<1ms TTL=128

> ping www.google.com
Ping www.google.com [172.217.31.132] 32바이트 데이터 사용:
172.217.31.132의 응답: 바이트=32 시간=64ms TTL=113
172.217.31.132의 응답: 바이트=32 시간=66ms TTL=113

> ping www.naver.com
Ping www.naver.com.nheos.com [223.130.195.95] 32바이트 데이터 사용:
요청 시간이 만료되었습니다.
요청 시간이 만료되었습니다.

 

다양한 결과를 아래와 같은 방식으로 parsing하여 시간 부분을 추출할 예정이다. OS 및 ping 출력 형식에 따라 time 부분을 잘라서 ms 단위를 us 단위로 변환한다.

 

bool PingTest::isWinKrOutputString(QString s, QString &r)
{
    // 127.0.0.1의 응답: 바이트=32 시간<1ms TTL=128
    // 172.217.31.132의 응답: 바이트=32 시간=64ms TTL=113

    QRegularExpression re(" 시간[=<](\\d)*(\\.){0,1}(\\d)*ms TTL=");
    QRegularExpressionMatch match = re.match(s, 0, QRegularExpression::PartialPreferFirstMatch);

    bool hasMatch = match.hasMatch();
    if (true == hasMatch) {
        qDebug() << "match : " << match.capturedTexts();

        QString responseTime = match.captured(0);
        responseTime.replace(QString(" 시간"), QString(""));
        responseTime.replace(QString(" TTL="), QString(""));
        responseTime.replace(QString("ms"), QString(""));

        r = responseTime;
        //qDebug() << "responseTime : " << r;

        return true;
    }

    return false;
}

 

ping 프로그램에 따라 1ms 미만을 <1ms 로 표시하기도 하고 0.987ms로 표시하기도 한다. 조건에 맞게 parsing 하고 <1ms에 대해서는 999us로 통일하여 표시한다.

qlonglong PingTest::getResponseTime(QString s)
{
    // =123
    // <1

    qlonglong responseTime = -1;
    if (true == s.startsWith(QString("="))) {
        s.replace(QString("="), QString(""));
        QStringList t = s.split(QString("."));
        if (2 == t.count()) {
            responseTime = (t[0].toLongLong() * 1000) + t[1].toLongLong();
        }
        else if (1 == t.count()) {
            responseTime = (t[0].toLongLong() * 1000);
        }
    }
    else if (true == s.startsWith(QString("<"))) {
        s.replace(QString("<"), QString(""));
        QStringList t = s.split(QString("."));
        if (2 == t.count()) {
            responseTime = (t[0].toLongLong() * 1000) + t[1].toLongLong() - 1;
        }
        else if (1 == t.count()) {
            responseTime = (t[0].toLongLong() * 1000) - 1;
        }
    }

    return responseTime;
}

 

결과는 아래와 같이 signal로 전달하도록 했다. mainwindow에서는 이 signal을 연결하여 정보를 받을 수 있다.

 

void PingTest::readyReadStandardOutput()
{
    if (m_pProcessPing->isReadable()) {
        QByteArray mOutputByteArray = m_pProcessPing->readAllStandardOutput();
        m_OutputString = QString::fromLocal8Bit(mOutputByteArray);
        QStringList outputStrings = convToLineByLine(m_OutputString);
        //qDebug() << m_OutputString;

        for (auto & line : outputStrings) {
            qDebug() << line;
            QString responseTimeString = "";
            qlonglong responseTime = -1;
            bool result = checkOutputString(line, responseTimeString);
            if (true == result) {
                responseTime = getResponseTime(responseTimeString);
                qDebug() << "responseTime : " << responseTimeString << ", " << responseTime;
            }

            emit sigGetResponseTime(responseTime);
        }
    }
}

 

ping 결과를 받으면 QPlainTextEdit에 시간을 출력한다. 시간은 us 단위로 표시한다.

 

connect(pPingTest, SIGNAL(sigGetResponseTime(qlonglong)), this, SLOT(slotGetResponseTime(qlonglong)));

 

void MainWindow::slotGetResponseTime(qlonglong us)
{
    QDateTime currTime = QDateTime::currentDateTime();

    if (us >= 0) {
        ui->editPingTimeRecord->textCursor().insertText("[" + currTime.toString("yyyy-MM-ddT hh:mm:ss") +
                                                    "] " + QString::number(us) + "us\n");
    }
    else {
        ui->editPingTimeRecord->textCursor().insertText("[" + currTime.toString("yyyy-MM-ddT hh:mm:ss") +
                                                    "] timeout\n");
    }
}

 

실행하면 아래와 같다.

 

 

정리되지 않은 코드지만 소스코드가 필요하시면 아래에서...

 

https://github.com/busymankr/bmPingTest

 

busymankr/bmPingTest

Contribute to busymankr/bmPingTest development by creating an account on GitHub.

github.com

 

bmPingTest-master.zip
0.01MB

 

그럼. 끝!!

댓글