본문 바로가기

프로그래밍/시스템

C++ Qt 핑 프로그램 만들기

반응형

 

핑 테스트 프로그램을 만들기 위해서 핵심적으로 사용되는 클래스는 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 (-!= 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 (-!= 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 (-!= 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 (-!= 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