ping을 구현하는 것도 방법이지만 ping 프로그램을 실행하여 결과를 사용하는 것도 좋은 방법이다.
이번에는 인터넷에서 쉽게 구할 수 있는 샘플을 사용하여 ping 명령어 실행해보려 한다.
목표는 ping을 실행하고 ping의 시간을 표시하는 것을 목표로 한다.
참조할 코드가 있으면 좋으니 아래 2개를 인터넷 검색으로 찾아 사용했다.
https://github.com/edhana/qt-ping-example
받아 실행하면 Qt 버전에 따라 다르겠지만, sleep() 함수 부분에서 문제가 생겨 수정했다.
2022.08.01 - [일하기/Qt] - warning: '_sleep' is deprecated
수정 후, 실행하면 아래와 같이 문제없이 돌아간다. 한글 때문에 아래와 같이 나오는데 그냥 넘어간다.
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
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
그럼. 끝!!
'놀기 > Qt' 카테고리의 다른 글
Qt 한글 깨짐 문제 (0) | 2023.09.23 |
---|---|
QT에서 SendMessage() 사용하기 (0) | 2023.09.09 |
USB 저장 장치 제거하기 (How to eject an external drive or USB stick) (0) | 2023.09.05 |
[Qt] Widget 크기에 맞게 폰트 조절하기 (feat. QLabel을 QPixmap으로 변환) (0) | 2023.08.27 |
[Qt] QMovie로 gif 재생이 안 될 때 ..... (0) | 2023.08.07 |
댓글