Russian Qt Forum
Ноябрь 26, 2024, 05:20 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QProcess и чтение ответа  (Прочитано 2727 раз)
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.
Но, возможно, есть варианты реализовать это как-то более грамотно?
Записан
mutineer
Гость
« Ответ #1 : Апрель 24, 2013, 14:44 »

Вынеси первый цикл в отдельный поток

Ну и неплохо было бы отработавшие QProcess хотя бы удалять
« Последнее редактирование: Апрель 24, 2013, 14:48 от mutineer » Записан
eXeLe
Гость
« Ответ #2 : Апрель 24, 2013, 16:04 »

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

ты запускаешь не процесс i число раз, ты создаешь i объектов QProcess, а указатель у тебя есть только на последний, из него ты и читаешь. Все остальные молотят впустую и никак друг друга не "перебивают"
Записан
RedDog
Гость
« Ответ #4 : Апрель 24, 2013, 16:14 »

ты запускаешь не процесс i число раз, ты создаешь i объектов QProcess, а указатель у тебя есть только на последний, из него ты и читаешь. Все остальные молотят впустую и никак друг друга не "перебивают"
как раз таки:
for(int i=0;i<sList.size();i++){
        ping = new QProcess ();
...}
создает и запускает i процессов.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.071 секунд. Запросов: 21.