【问题标题】:Writing custom QIODevice with 2 channels编写具有 2 个通道的自定义 QIODevice
【发布时间】:2017-08-15 14:00:58
【问题描述】:

我正在尝试实现自定义 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 设置为模式。如果返回真 成功的;否则返回假。应该调用这个函数 从 open() 的任何重新实现或其他打开 设备。

所以我必须从我重写的Open() 方法中调用它,但我查看了这个方法的实现,发现它正在将通道数设置为 1。我该如何更改这个数字?

我从 QIODevice 继承的那些缓冲区是做什么用的,我应该如何使用它们?

我错过了创建自定义 QIODevice 的意义吗?如果有,请给我解释一下。

【问题讨论】:

  • 你可能会从 QProcess 中获得灵感,它提供了 stdin、stdout 和 stderr 的接口......也是 QIODevice 的子类。
  • 感谢您的评论,我会看看这个。

标签: c++ qt qiodevice


【解决方案1】:

您不太可能需要在这里继承QIODevice,只需设计和实现具有您需要的语义的接口,例如:

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

QIODevice 是一个通用接口,用于从文件、套接字、串行端口等不同来源读取/写入字节流

【讨论】:

  • 首先感谢您的回答。非常感激。但是我认为,如果我正在创建一个作为 IO 设备抽象的类,那么将具有非常有用的接口的 QIODevice 子类化将是一个好习惯。它的主要优势在于,将来我可以通过将这个对象替换为任何 QIODevice 对象来将我的应用程序重用于不同的设备。继承 QIODevice 的第二大优势是我可以使用这样有用的类,例如 QDataStream,它在构造函数中采用 QIODevice。
猜你喜欢
  • 2011-10-23
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多