핑 테스트 프로그램을 만들기 위해서 핵심적으로 사용되는 클래스는 QProcess다.
대략적인 로직은 QProcess로 호스트에 Ping을 날려서 돌아오는 결과값을 파싱하게된다.
다음은 예제 코드다.
192.168.0.2 핑테스트
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
class MainWindow {
private slots:
void OnPing();
void OnPingEnded();
private:
QProcess mPingProcess;
};
void MainWindow::OnPing()
{
connect(&mPingProcess,SIGNAL(finished(int,QProcess::ExitStatus)) , this , SLOT(OnPingEnded()) );
mPingProcess2.start("ping",QStringList() << "-n" << "1" << "192.168.0.2");
//Windows에서 대상에 도달 할 수없는 경우 ping 메서드는 0 종료 코드 이벤트를 반환합니다.
// -n은 에코요청수 옵션입니다.
}
//핑 출력결과를 구문 분석합니다.
void MainWindow::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";
}
}
}
|
cs |
192.168.0.2 ~ 192.168.0.n [ 순차적 핑테스트 - 한 프로세스가 끝날 때 까지 대기 ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
void MainWindow::OnPing()
{
// echo option in window - n
// echo option in linux - c
#if defined(WIN32)
QString parameter = "-n";
#else
QString parameter = "-c";
#endif
int n = 10;
connect(&mPingProcess,SIGNAL(finished(int,QProcess::ExitStatus)) , this , SLOT(OnPingEnded()) );
for(int i = 2; i<=n; i++){
mPingProcess.start("ping",QStringList() << parameter << "1" << "192.168.0."+QString::number(i) );
mPingProcess.waitForFinished(); // 이전 프로세스가 끝날 때까지 대기
}
}
void MainWindow::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";
}
}
}
|
cs |
192.168.0.2 ~ 192.168.0.n [ 멀티 핑테스트 - 다수의 프로세스를 한번에 실행 ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
void MainWindow::OnPing()
{
#if defined(WIN32)
QString parameter = "-n";
#else
QString parameter = "-c";
#endif
QStringList hosts;
for(int i=2; i<=10; i++)
{
QString host = "192.168.0."+QString::number(i);
hosts.append(host);
}
for (const QString &host : hosts) {
auto process = new QProcess(this);
process->start("ping" ,QStringList() << parameter << "1" << host );
// connect slot 람다식 코드 작성
connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[process](int exitCode, QProcess::ExitStatus exitStatus)
{
QString ip = process->arguments().at(2);
QByteArray output = process->readAllStandardOutput();
if (!output.isEmpty())
{
if (-1 != QString(output).indexOf("ttl", 0, Qt::CaseInsensitive))
{
qDebug() << "PING OK" << ip;
}
else
{
qDebug() << "PING KO" << ip;
}
}
process->deleteLater();
});
}
}
|
cs |
단 QProcess는 62개이상 실행되면 다음과 같은 에러가 출력된다.
QWinEventNotifier: Cannot have more than 62 enabled at one time
따라서 /24대역 (0.1부터 254)까지 스캔하려고 하는 경우
62개의 프로세스를 먼저 돌린 뒤 실행이 끝난 프로세스가 있다면
나머지 QProcess가 실행되도록 해야한다. 이럴 때 QEventLoop , QTimer를 이용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#if defined(WIN32)
QString parameter = "-n";
#else
QString parameter = "-c";
#endif
QStringList hosts;
for(int i=2; i<=254; i++)
{
QString host = "192.168.0."+QString::number(i);
hosts.append(host);
}
for (const QString &host : hosts) {
while(true)
{
if (run_cnt < 62)
{
run_cnt++;
auto process = new QProcess(this);
process->start("ping" ,QStringList() << parameter << "1" << host );
connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
[=](int exitCode, QProcess::ExitStatus exitStatus)
{
QString ip = process->arguments().at(2);
QByteArray output = process->readAllStandardOutput();
if (!output.isEmpty())
{
if (-1 != QString(output).indexOf("ttl", 0, Qt::CaseInsensitive))
{
qDebug() << "PING OK" << ip;
}
else
{
qDebug() << "PING KO" << ip;
} run_cnt--;
}
process->deleteLater();
}); break;
} else {
QEventLoop loop;
QTimer timer;
timer.setSingleShot(true);
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
timer.start(100);
loop.exec();
}
}
}
|
cs |
QProcess의 실행가능여부를 파악하기 위해 무한루프를 걸어놓고 현재 실행갯수를 카운트한다.
완료된 QProcess는 현재 실행갯수를 감소시켜서 나머지 QProcess가 실행되도록 하고 ,
break를 통해 루프문을 빠져나온다.
실행갯수가 62개를 넘었을 때 else문이 동작하게 되는데
이 때 이벤트 루프로 진입해야한다.
이유는 충분히 시간이 필요한 작업을 할 때는 작업을 잠깐 다른 스레드로 옮겨놓아야
무한루프로 인한 블록킹을 막을 수 있기 때문이다.
timer를 통해 0.1초마다 loop를 진입했다 , 빠져나왔다를 반복하면서
QProcess의 실행가능여부를 확인하게 된다.
'프로그래밍 > 시스템' 카테고리의 다른 글
C++ Qt 윈도우 배포용 라이브러리 추가 (0) | 2018.05.04 |
---|---|
C++ 11 람다표현식(Lambda expression) (0) | 2018.05.03 |
C++ Qt 잡지식 (0) | 2018.03.19 |
C++ Qt 엑셀 사용하기 (0) | 2018.03.19 |
C++ Qt XML (0) | 2018.03.19 |