2016-02-05 3 views
0

Я пишу клиент для приложения клиент/сервер. Клиенты должны войти в систему, используя окно входа в систему. Если вход успешно завершен, появляется окно ожидания (это только окно, содержащее метку). На стороне сервера есть барьер, ожидающий входа в систему n клиентов; когда это происходит, сообщение транслируется, ожидается, что окно ожидания закрывается, и для каждого клиента появляется новое окно.Qt создает диалоговое окно, ожидающее сетевого события

Сетевой интерфейс реализован мной, используя низкоуровневые функции, а не функциональность, предоставляемую Qt.

Фактический цикл ожидания что-то вроде этого:

char buffer[256]; 
while (strcmp(buffer, "proceed")) 
    read(sockfd, buffer, 256); 

Проблема заключается в том, что если я начну этот цикл в основном потоке, блоки приложений, по понятным причинам.

Как я могу сделать этот цикл запущенным, а не заблокировать приложение, и закрыть диалоговое окно, когда оно закончится?

Позже изменения: я также попытаться использовать объекты QThread, но по причинам, которые я еще не до конца понимаю, приложение по-прежнему падает:

class WaitLoop : public QThread { 
public: 
    WaitLoop(NetworkHandler &network) : network(network) {} 
private : 
    NetworkHandler &network; 
    void run() { 
     this->network.waitForGameStart(); 
    } 
}; 

В диалоговых ожиданиях конструктора:

WaitLoop *waitLoop = new WaitLoop(network); 
connect(waitLoop, SIGNAL(finished()), this, SLOT(gameStartSlot())); 
waitLoop->start(); 

Приложение все еще работает с использованием этого подхода.

+0

Возможно, диалог прогресса может работать; http://doc.qt.io/qt-4.8/qprogressdialog.html –

+0

реализовать рабочий объект с этой функциональностью и запустить в отдельном потоке. когда вы получаете сообщение, просто выпустите сигнал от рабочего объекта, который вы можете подключить к слоту «закрыть()» в диалоговом окне. – ramtheconqueror

+0

@ramtheconqueror Теперь у вас есть две проблемы, а не одна. Нитки не являются универсальным средством. –

ответ

0

Самый безопасный способ приблизиться к этому не будет использовать низкоуровневые функции, потому что вы не пишете на C. Используйте как минимум QAbstractSocket для обертывания sockfd. Метод setSocketDescriptor позволяет это сделать.

Ваш код становится неблокирующий и асинхронный:

class Controller : public QObject { 
    Q_OBJECT 
    QStateMachine m_sm; 
    QState s_init{&m_sm}, s_proceeding{&m_sm}; 
    QAbstractSocket m_socket; 
    Q_SIGNAL void proceed(); 
    Q_SLOT void onData() { 
    auto data = m_socket.readAll(); 
    if (data.contains("proceed")) proceed(); 
    } 
public: 
    Controller(QObject * parent = 0) : QObject(parent) { 
    connect(&m_socket, &QIODevice::readyRead, this, &Controller::onData); 
    s_init.addTransition(this, &Controller::proceed, &s_proceeding); 
    m_sm.setInitialState(&s_init); 
    m_sm.start(); 
    } 
    bool setup(quintptr fd) { 
    return m_socket.setSocketDescriptor(fd); 
    } 
}; 

Благодаря использовании государственного аппарата, его легко добавить больше состояний, реагировать на их переходы (см QState::onEntry сигнала и т.д.), и убедитесь, что поведение верное. Исчерпание пользовательского символа UML заставляет вас думать об обработке угловых случаев и т. Д. Для полного примера см. this answer.

+0

Я знаю, что это лучшая практика и объединение низкоуровневых процедур обработки сети с высоким уровнем кода - не лучший подход. Однако это требование приложения, чтобы использовать низкоуровневые процедуры обработки сети. – Paul92

+0

@ Paul92 Затем интегрируйте файловые дескрипторы, используемые в вашей сети, с циклом событий. Ваша библиотека при правильном проектировании должна предоставить пользователю набор дескрипторов файлов, и пусть пользователь уведомляет * это *, когда какое-либо действие обнаруживается в fds. Затем ваш Qt-код будет использовать 'QSocketNotifier' для возврата в вашу библиотеку, чей-то код может использовать цикл событий glib или просто« опрос »или« дрожь »,« выбрать ». В противном случае поместите все это в поток.Я не знаю, что вы делаете неправильно, вы недостаточно показываете код. –

Смежные вопросы