использование функций блокировки вместе с сигналами (QTcpSocket) - PullRequest
0 голосов
/ 16 ноября 2018

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

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

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

Примечание : мы не рекомендуем использовать функции блокировки вместе с сигналы. Следует использовать одну из двух возможностей.

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

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

1 Ответ

0 голосов
/ 20 ноября 2018

Я решил проблему, следуя совету Феликс о 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.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...