Qt是否有一個QIODevice
對可用於內部-進程點到點通信?Qt中是否存在進程內本地管道?
可以使用具體的QTCPSocket
或QLocalSocket
,但服務器端連接API有點麻煩,而且通過操作系統強制數據看起來很浪費。
Qt是否有一個QIODevice
對可用於內部-進程點到點通信?Qt中是否存在進程內本地管道?
可以使用具體的QTCPSocket
或QLocalSocket
,但服務器端連接API有點麻煩,而且通過操作系統強制數據看起來很浪費。
以下是一個可用的基本實現。它使用內部信號插槽對將數據推送到另一個端點。這樣,連接的任何一端都可以存在於任何線程中,並且可以在線程之間移動端點而不會丟失數據或引發任何比賽。
專用QRingBuffer
用於代替重新發明車輪。將QT += core-private
添加到.pro
文件以使其可用。
在沒有其他端點集的情況下進行初始化時,必須將明確的nullptr
作爲第一個參數傳遞給構造函數。這有助於避免端點與對象父級之間的混淆。
如果您希望實例化一個打開的管道,可能經常出現這種情況,您可以將I/O模式傳遞給構造函數。典型用途:
int main(/*…*/)
{
/*…*/
AppPipe end1 { nullptr, QIODevice::ReadWrite };
AppPipe end2 { &end1, QIODevice::ReadWrite };
// the pipes are open ready to use
/*…*/
}
無論您寫入一個管道,最終都會成爲另一個管道中的可讀數據,反之亦然。所有QIODevice
語義保持 - 您可以連接到readyRead
信號,使用管道QDataStream
或QTextStream
等。與任何QIODevice
一樣,您只能使用thread()
中的類,但另一個端點可以在任何線程,並且都可以根據需要在線程之間移動,而不會丟失數據。
如果另一個管端沒有打開並且可讀,則即使它們成功寫入也是空操作。關閉管道將清除讀緩衝區,以便可以重新打開以供重用。
hasIncoming
和hasOutgoing
信號用於monitoring數據通過管道。
// https://github.com/KubaO/stackoverflown/tree/master/questions/local-pipe-32317081
#include <QtCore>
#include <private/qringbuffer_p.h>
/// A simple point-to-point intra-process pipe. The other endpoint can live in any
/// thread.
class AppPipe : public QIODevice {
Q_OBJECT
QRingBuffer m_buf;
Q_SLOT void _a_write(const QByteArray & data) {
if (! openMode() & QIODevice::ReadOnly) return; // We must be readable.
m_buf.append(data);
emit hasIncoming(data);
emit readyRead();
}
public:
AppPipe(AppPipe * other, QIODevice::OpenMode mode, QObject * parent = {}) :
AppPipe(other, parent) {
open(mode);
}
AppPipe(AppPipe * other = {}, QObject * parent = {}) : QIODevice(parent) {
addOther(other);
}
void addOther(AppPipe * other) {
if (other) {
connect(this, &AppPipe::hasOutgoing, other, &AppPipe::_a_write, Qt::UniqueConnection);
connect(other, &AppPipe::hasOutgoing, this, &AppPipe::_a_write, Qt::UniqueConnection);
}
}
void removeOther(AppPipe * other) {
disconnect(this, &AppPipe::hasOutgoing, other, &AppPipe::_a_write);
disconnect(other, &AppPipe::hasOutgoing, this, &AppPipe::_a_write);
}
void close() override {
QIODevice::close();
m_buf.clear();
}
qint64 writeData(const char * data, qint64 maxSize) override {
if (maxSize > 0)
hasOutgoing(QByteArray(data, maxSize));
return maxSize;
}
qint64 readData(char * data, qint64 maxLength) override {
return m_buf.read(data, maxLength);
}
qint64 bytesAvailable() const override {
return m_buf.size() + QIODevice::bytesAvailable();
}
bool canReadLine() const override {
return QIODevice::canReadLine() || m_buf.canReadLine();
}
bool isSequential() const override { return true; }
Q_SIGNAL void hasOutgoing(const QByteArray &);
Q_SIGNAL void hasIncoming(const QByteArray &);
};
# local-pipe-32317081.pro
QT = core-private
TARGET = local-pipe-32317081
CONFIG += c++11
TEMPLATE = app
SOURCES = main.cpp