LINUX.ORG.RU

Псевдотерминал

 , , , ,


0

1

Всем привет! Только начинаю программировать на unix и одно из заданий моих - написать псевдотерминал.

Вот соответственно та часть кода, которую я пишу. Мне удалось написать только то, чтобы при нажатии на кнопку, отправлялась команда из тестового поля и результат записывало в поле для вывода. Проблема заключается в том, что команды, которые сразу выдают ответ (типа df) проходят, а вот на команде ping приложение зависает и в поле для вывода не дает ничего. Надеюсь, что вы поможете в этом мне разобраться! Заранее спасибо!

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(nashSlot()));
}

MainWindow::~MainWindow()
{
    delete ui;
}




void MainWindow::nashSlot()
{
    QString str1 = ui->lineEdit->text(); // получаем строку из первого QLineEdit
    QProcess proc;
    proc.start(str1);
    proc.waitForFinished();

    QByteArray output = proc.readAll();
    proc.close();
    ui->textBrowser->setText(output);

}

Поставь теги qt и c++, а то ты пингуешь не тех, кого надо.

Bfgeshka ★★★★★
()

Могу предположить что ты запускаешь просто 'ping', который в линуксах сам не завершается. Можно вот так к примеру:

ping -c 4 8.8.8.8

4 тика и завершится. Можно вообще один для тестов.

Kronick
()
Ответ на: комментарий от Kronick

да, именно так и делаю, но мне надо решить эту проблему, а не уйти от нее, мне надо, чтобы в textBrowser выводилось в реальном времени, как это выполняется, а не по окончании программы, которая по факту бесконечна

checkdimon
() автор топика

То, что ты делаешь — это не псевдотерминал.

anonymous
()

Не знаю как это сделать на Qt, но ты же совершенно ясно пишешь: proc.waitForFinished();
Очевидно, что ты получишь вывод результата только ПОСЛЕ завершения вызываемой программы. Тебе нужно принципиально менять подход.

Deleted
()
Ответ на: комментарий от Deleted

5 секунд гугления: QByteArray QProcess::readAllStandardOutput()
По идее вернёт тебе текущее содержимое стандартного output вне зависимости от состония программы.
КОроче, в цикле (пока QProcess::ProcessState указывает на работу программы) дёргаешь QProcess::readAllStandardOutput() и делаешь с ним всё что хочешь.
С тебя пирожок:)

Deleted
()

Не делай wait. Используй сигналы readyReadStandardError и readyReadStandardOutput и в них соответственно методы readAllStandardError и readAllStandardOutput для чтения вывода запущенной программы. И сделай кнопку и по ее нажатию метод close у программы.

rumgot ★★★★★
()
Ответ на: комментарий от Deleted

В Qt сигналы и слоты нужно использовать, а не циклами велосипедить.

rumgot ★★★★★
()

Еще есть такая штука, что STDOUT у процесса обычно буферизированный (построчно). Что тебе надо — non-blocking io + popen. Наверное в Qt есть какие-нибудь обертки над этим.

В любом случае, ждать в потоке GUI, как у тебя в коде:

void MainWindow::nashSlot()
{
  // ...
  proc.waitForFinished();
  // ...
}
-- это плохо. И именно из-за этого кажется, что пограмма зависла. GUI должно быть отзывчивым. По этому ждать можно только в отдельных (от GUI) потоках. А лучше всего запроэктировать так, чтоб не надо было ждать.

Как сказал выше ZweiStein QProcess::readAllStandardOutput() — похоже на non-blocking io. А QProcess::run() — обертка над popen (и другими системными вызовами).

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 4)

И упомяну также (хотя это и очевидно), что подключать сигналы нужно ДО выполнения proc.start().

rumgot ★★★★★
()
Ответ на: комментарий от KennyMinigun

Поэтому не нужно использовать waitForFinished, просто нужно запустить и далее по сигналам смотреть.

rumgot ★★★★★
()
Ответ на: комментарий от checkdimon

но если его убрать, это вопрос не решае

Не убрать, а заменить. Самое простое решение «в лоб»: запустить поток (QThread) который будет опрашивать запущенный процесс (readAllStandardOutput()) и отсылать полученное в MainWindow. Поскольку я не спец. в Qt, то не скажу точно. Скорее всего что-то такое уже придумано и надо использовать нужные сигналы.

Естественно, тот же поток может «управлять процессом»: следить не помер ли процесс или принудительно его завершить. По завершению процесса можно разблокировать кнопку «Запустить процесс», чтоб можно было запустить следующий процесс.

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 2)
Ответ на: комментарий от rumgot

Как я понял, мне следует с сигналами сделать так. Проблема только есть в том, что ругается на том, что я мол создал не правильно connect

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>

QProcess proc;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(nashSlot()));
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(nashSlot2()));
}

MainWindow::~MainWindow()
{
    delete ui;
}




void MainWindow::nashSlot()
{
    QString str1 = ui->lineEdit->text(); // получаем строку из первого QLineEdit
    connect(proc, SIGNAL(readyReadStandardOutput()), SLOT(slotDataOnStdout()));
    proc.start(str1);
}
void MainWindow::nashSlot2()
{
    proc.close();
}
void MainWindow::slotDataOnStdout()
{
    QByteArray output = proc.readAllStandardOutput();
    ui->textBrowser->setText(output);
}

checkdimon
() автор топика
Ответ на: комментарий от SR_team

Спасибо, помог. Оставляю код, может кому пригодится

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QProcess>

QProcess proc;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(nashSlot()));
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(nashSlot2()));
}

MainWindow::~MainWindow()
{
    delete ui;
}




void MainWindow::nashSlot()
{
    QString str1 = ui->lineEdit->text(); // получаем строку из первого QLineEdit
    connect(&proc, &QProcess::readyReadStandardOutput, this, &MainWindow::slotDataOnStdout);
    proc.start(str1);
}
void MainWindow::nashSlot2()
{
    proc.close();
}
void MainWindow::slotDataOnStdout()
{
    QString output = proc.readAllStandardOutput().toStdString().c_str();
    ui->textBrowser->append(output);
}
checkdimon
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.