你可能會調用readAll
響應可用之前。您應該將您的代碼掛接到readyRead
信號,以便每次準備好讀取新數據塊時都會收到通知。請記住,readyRead
可以以可讀取的任意數量的字節發送 - 至少它只會是一個字節。您不能期望數據以任何特定的方式被分塊/阻塞,因爲串行端口不會充當基於消息的通信設備。您的接收器代碼必須能夠將數據從小塊組合在一起,並在獲取所需的所有數據時採取相應措施。
例如,假設設備響應具有固定的已知長度。您只想在完整回覆到達時作出反應。例如:
class Protocol : public QObject {
Q_OBJECT
QBasicTimer m_timer;
QPointer<QIODevice> m_port;
int m_responseLength = 0;
int m_read = 0;
void timerEvent(QTimerEvent * ev) override {
if (ev->timerId() != m_timer.timerId()) return;
m_timer.stop();
emit timedOut();
}
void onData() {
m_read += m_port->bytesAvailable();
if (m_read < m_responseLength)
return;
m_timer.stop();
emit gotResponse(m_port->read(m_responseLength));
m_read -= m_responseLength;
m_responseLength = 0;
}
public:
Q_SIGNAL void gotResponse(const QByteArray &);
Q_SIGNAL void timedOut();
Q_SLOT void sendCommand(const QByteArray & cmd, int responseLength, int cmdTimeout) {
m_responseLength = responseLength;
m_port->write(cmd);
m_timer.start(cmdTimeout, this);
}
explicit Protocol(QIODevice * port, QObject * parent = nullptr) :
QObject(parent), m_port(port) {
connect(m_port, &QIODevice::readyRead, this, &Protocol::onData);
}
};
...
Protocol protocol(0,0);
protocol.sendCommand({"foo"}, 10, 500);
QMetaObject::Connection cmd1;
cmd1 = QObject::connect(&protocol, &Protocol::gotResponse, [&]{
QObject::disconnect(cmd1);
qDebug() << "got response to foo";
});
QObject::connect(&protocol, &Protocol::timedOut, []{ qDebug() << "timed out :("; });
感謝這是一個非常有幫助的迴應! – jxb458