Russian Qt Forum

Qt => Вопросы новичков => Тема начата: eXeLe от Апрель 24, 2013, 14:42



Название: QProcess и чтение ответа
Отправлено: eXeLe от Апрель 24, 2013, 14:42
Понадобилось добавить в программу небольшую пинговалку для проверки доступности ряда серверов.
Загоняю список серверов в QStringList с именем sList, после чего прогоняю подобным циклом:

Код:
    for(int i=0;i<sList.size();i++){
        ping = new QProcess ();
        ping->start("ping", QStringList() << sList[i],QIODevice::ReadOnly);
ping->waitForFinished(300);
        QString p_stdout = ping->readAllStandardOutput();
        ping->close();
        int TTL=p_stdout.indexOf("TTL",0);
        if(TTL>=0){
            qDebug()<<"Сервер "<<sList[i]<< " доступен.";
        }
        else{
            qDebug()<<"Сервер "<<sList[i]<< " НЕ доступен!";
        }
    }

Но проблема тут в том, что на время waitForFinished(300); интерфейс подвисает. А когда кол-во серверов много, а проверка запускается часто - получаем зависшую прогу.

Вычитал, что можно использовать сигнал readyReadStandardOutput.
Попробовал сделать так:
Код:
for(int i=0;i<sList.size();i++){
        ping = new QProcess ();
        QObject::connect(ping, SIGNAL(readyReadStandardOutput ()), this, SLOT(print_ping()) );
        ping->start("ping", QStringList() << sList[i],QIODevice::ReadOnly);
    }
Код:
void ProgramName::print_ping()
{
    QString output = ping->readAllStandardOutput ();
    qDebug()<<output;
}
но print_ping вызывается неоднократно в рамках пинга одного сервера и как итог - мы имеем обновляющуюся строку QString output, которую так легко парсить на наличие в ней фразы TTL - не получится. Объединять поступающие строки в одну общую - тоже проблематично, так как пингуем несколько серверов подряд. И вторая проблема тут - мы никак не передаем имя сервера и обрабатывать результат пинга - к какому серверу оно относится - проблемно.

Какие есть способы решения, чтобы не подвисал UI и вместе с тем - иметь удобную обработку результатов?

Пока вижу только извращенный способ с записью всех результатов пинга всех серверов в одну строку, а потом уже, имя массив хостнеймов серверов, парсить куски этой строки для i-го сервере sList[ i ] в промежутках строки между sList[ i ] и sList[i+1] на наличие фразы TTL.
Но, возможно, есть варианты реализовать это как-то более грамотно?


Название: Re: QProcess и чтение ответа
Отправлено: mutineer от Апрель 24, 2013, 14:44
Вынеси первый цикл в отдельный поток

Ну и неплохо было бы отработавшие QProcess хотя бы удалять


Название: Re: QProcess и чтение ответа
Отправлено: eXeLe от Апрель 24, 2013, 16:04
Глянул для начала вывод из ping->readAllStandardOutput (); при использовании отдельной функции для чтения ответа с использованием readyReadStandardOutput.
Как оказалось, выводится там, только последняя из команд, что в принципе логично, наверное, потому что мы циклом запускаем процесс i число раз и ждем ответа, так что процессы ping->start, по видимому "перебивают" друг друга и выполняется только последний.


Название: Re: QProcess и чтение ответа
Отправлено: mutineer от Апрель 24, 2013, 16:07
ты запускаешь не процесс i число раз, ты создаешь i объектов QProcess, а указатель у тебя есть только на последний, из него ты и читаешь. Все остальные молотят впустую и никак друг друга не "перебивают"


Название: Re: QProcess и чтение ответа
Отправлено: RedDog от Апрель 24, 2013, 16:14
ты запускаешь не процесс i число раз, ты создаешь i объектов QProcess, а указатель у тебя есть только на последний, из него ты и читаешь. Все остальные молотят впустую и никак друг друга не "перебивают"
как раз таки:
for(int i=0;i<sList.size();i++){
        ping = new QProcess ();
...}
создает и запускает i процессов.