Использование функций блокировки вместе с сигналами (QTcpSocket)

Я пишу AsyncSocket, который использует QTcpSocket для работы с некоторыми серверами. Они (серверы) были написаны давно, и у меня нет возможности их изменить.

Итак, проблема в - отсутствие сигнала readyRead, если сервер не смог распознать сообщение (потому что он ничего не сделал с типом сообщения default). Я думаю, что это проблема сервера, потому что он все равно должен ответить ... но это не мой собственный код, и я должен использовать его как есть.

Я думал использовать QAbstractSocket::waitForReadyRead(int msecs), но нашел в Документация Qt (конец раздела «подробности»):

Note: We discourage the use of the blocking functions together with signals. One of the two possibilities should be used.

Итак, я немного запутался, почему мне не следует использовать такой метод блокировки:

void AsyncSocket::send(const QByteArray &msg)
{
    socket->write(msg);

    if (!socket->waitForReadyRead(msecs))
        qDebug() << "Warning! ReadyRead were not emitted";
}

Сервер работает так:

switch(received_msg.type)
{
    case TYPE_ONE: // do smth
        break;

    case TYPE_TWO: // do smth
        break;

    case TYPE_N:   // do smth
        break;

    default: 
        // do NOTHING
}

Мои занятия:

class AsyncSocket
{
public:
    void connectToHost(const QString &host, qint16 port);
    void send(const QByteArray &msg);
    void disconnectFromHost();

    // other public members

public slots:
    void connected();
    void readyRead();
};

ОБНОВИТЬ: может быть полезно перехватывать отсутствующие сигналы readyRead для организации очереди сообщений с помощью AsyncSocket

Я не понимаю, о чем вы спрашиваете. Итак, ваша проблема в том, что сервер не отвечает на определенные сообщения, и вы хотите определить, когда это произойдет?

Felix 16.11.2018 10:34

Да, ты прав. Qt doc говорит, что использовать блочные методы - не лучшая идея. Но не совсем ясно, какова альтернатива.

Bogdan 16.11.2018 10:36

Тогда у вас есть 2 варианта. Либо вы ждете, как описано выше (но это заблокирует ваше приложение и обычно не рекомендуется), либо вы используете QTimer для запуска тайм-аута, если пройдет много времени до того, как будет выпущен readyRead

Felix 16.11.2018 10:38
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я решил проблему, следуя совету Феликс по поводу QTimer, вот так:

class AsyncSocket
{
public:
    void connectToHost(const QString &host, qint16 port);
    void send(const QByteArray &msg);
    void disconnectFromHost();

    // other public members
signals:
    void dataReady(const QByteArray &data);

public slots:
    void connected();
    void readyRead();

private slots:
    // I created the timer timeout signal here connected in AsyncSocket constructor
    void missRead(); 
private:
    QTimer *timer; // and timer pointer here allocated in constructor also
};

Я запускаю таймер, когда пользователь отправляет сообщение:

bool AsyncSocket::send(const QByteArray &msg, int responseSize)
{
    // successfull sending code here

    timer->start(msecs);
    return true;
}

И я использую сигналы для обработки таких случаев чтения:

void AsyncSocket::readyRead() // successfull reading
{
    if (socket->bytesAvailable() == responseSize) // buffer has all data
    {
        timer->stop();
        emit (dataReady(socket->readAll()));
        // reset device, clear buffer, etc.
    }
}

void AsyncSocket::missRead() // server stoped to reply
{
    timer->stop();
    emit(dataReady(QByteArray()));
    // reset device, clear buffer, etc.
}

Другие вопросы по теме