Написание пользовательского QIODevice с 2 каналами

Я пытаюсь реализовать собственный QIODevice.

У меня есть детектор, который будет использовать 2 сокета tcp, один для отправки команд и получения ответов, другой только для чтения данных.

как мне это сделать? Я попытался создать свой класс, вывести его из QIODevice и реализовать чисто виртуальные методы, но столкнулся с некоторыми трудностями.

У меня есть следующий фрагмент кода:

class Detector : public QIODevice {
    Q_OBJECT
    Q_DISABLE_COPY(MasterDevice)

public:
    enum CHANNEL_TYPE {
        DataChannel,
        ControlChannel
    };

private:
    QTcpSocket *controlDevice;
    QTcpSocket *dataDevice;

    QHostAddress hostAddress;

    quint16 dataPort;
    quint16 controlPort;

public:
    explicit Detector(QObject *parent, QHostAddress hostAddress, quint16 dataPort, quint16 controlPort)
        : QIODevice(parent)
        , hostAddress(hostAddress)
        , dataPort(dataPort)
        , controlPort(controlPort)
    {
        controlDevice = new QTcpSocket(this);
        connect(controlDevice, SIGNAL(readyRead()),this, SLOT(controlChannelReadReady()));

        dataDevice = new QTcpSocket(this);
        connect(dataDevice, SIGNAL(readyRead()),this, SLOT(dataChannelReadReady()));
    }

    virtual ~Detector() {}

    bool open(OpenMode mode) override {
        QIODevice::open(mode);

        controlDevice->connectToHost(hostAddress, controlPort, QTcpSocket::ReadWrite);
        dataDevice->connectToHost(hostAddress, dataPort, QTcpSocket::ReadOnly);
    }

    qint64 readData(char *data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentReadChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->read(data, maxSize);
    }

    qint64 writeData(const char * data, qint64 maxSize) override {
        QTcpSocket *socket;

        switch ( currentWriteChannel() ) {
        case DataChannel:
            socket = dataDevice;
            break;
        case ControlChannel:
            socket = controlDevice;
            break;
        default:
            return -1;
            break;
        }

        return socket->write(data, maxSize);
    }

private slots:
    void controlChannelReadReady() {
        emit channelReadyRead(ControlChannel);
    }

    void dataChannelReadReady() {
        emit channelReadyRead(DataChannel);
    }
};

Итак, в основном мой вопрос заключается в том, как мне обрабатывать эти каналы, потому что, например, от qt documentation у меня есть это

bool QIODevice::open(OpenMode mode)

Открывает устройство и устанавливает его OpenMode в режим. Возвращает true в случае успеха; в противном случае возвращает ложь. Эту функцию следует вызывать из любых повторных реализаций open() или других функций, открывающих устройство.

Поэтому мне приходится вызывать его из моего переопределенного метода Open(), но я посмотрел на реализацию этого метода и увидел, что он устанавливает количество каналов равным 1. Как я могу изменить это число?

Для чего нужны те буфера, которые я наследую от QIODevice, как мне их использовать?

Я упустил смысл создания пользовательского QIODevice? Если это так, пожалуйста, объясните мне это.


person notfound404    schedule 15.08.2017    source источник
comment
Вы можете получить вдохновение от QProcess, который предоставляет интерфейс для stdin, stdout и stderr... и также является подклассом QIODevice.   -  person hyde    schedule 15.08.2017
comment
Спасибо за ваш комментарий, я посмотрю на это.   -  person notfound404    schedule 16.08.2017


Ответы (1)


Вряд ли вам нужно создать подкласс QIODevice здесь, просто спроектируйте и реализуйте интерфейс с необходимой вам семантикой, например:

sendCommand();
responseReceived();
dataReady();
...
etc

QIODevice — это общий интерфейс для чтения/записи потоков байтов из/в различные источники, такие как файлы, сокеты, последовательные порты и т. д.

person mbg033    schedule 15.08.2017
comment
Прежде всего, спасибо за ваш ответ. Очень признателен. Однако я подумал, что если я создаю класс, который является абстракцией устройства ввода-вывода, было бы хорошей практикой создать подкласс QIODevice, который имеет очень полезный интерфейс. Основным преимуществом этого будет тот факт, что в будущем я смогу повторно использовать свое приложение с разными устройствами, просто заменив этот один объект любым объектом QIODevice. Второе большое преимущество подкласса QIODevice заключается в том, что я смогу использовать такие полезные классы, как, например, QDataStream, который принимает QIODevice в конструкторе. - person notfound404; 16.08.2017