跨进程通信之QLocalSocket

跨进程通信之QLocalSocket


苏轼 - 《临江仙·送钱穆父

一别都门三改火,天涯踏尽红尘。
依然一笑作春温。
无波真古井,有节是秋筠。

惆怅孤帆连夜发,送行淡月微云。
尊前不用翠眉颦。
人生如逆旅,我亦是行人。

QLocalSocketQLocalServer。这是在 同一台机器上进行进程间通信(IPC) 的Qt解决方案。

graph TD A[本地进程间通信 IPC] --> B[QLocalServer] A --> C[QLocalSocket] B --> D[服务器端<br>监听连接] C --> E[客户端<br>发起连接] D --> F[基于系统本地套接字<br>Windows: 命名管道<br>Unix: Unix Domain Socket] E --> F F --> G[高性能<br>无需网络协议栈<br>数据不经过网卡]

是什么?

  • QLocalServer:类似于 QTcpServer,但用于本地连接。它监听一个"服务器名称",等待客户端连接。
  • QLocalSocket:类似于 QTcpSocket,但用于本地连接。客户端用它连接到 QLocalServer

工作原理

它们基于操作系统的本地进程通信机制:

  • Windows:命名管道(Named Pipes)
  • Unix/Linux/macOS:Unix 域套接字(Unix Domain Sockets)

优势:比网络通信更快、更安全(不经过网络接口卡)。

使用案例(Qt官方案例 localfortuneclient/localfortuneserver)

QLocalSocket端核心代码

本地服务器端发送的报文格式:

    QDataStream out(&block, QIODevice::WriteOnly);
    out << quint32(message.size());
    out << message;
Client::Client()
{
    QLocalSocket* localSocket = new QLocalSocket(this);
    
    // 连接本地服务器
    connect(pshBtnConnectServer, &QPushButton::clicked, [&]()
    {
        localSocket->abort();
    	localSocket->connectToServer(hostLineEdit->text());
        
        // 后续逻辑,每个指定间隔,重新连接服务器.
    });
    
    // 从服务器读取类容(简化版接收代码)
    connect(pshBtnReadFromServer, &QPushButton::readyRead, [&]()
    {
        QDataStream in;
		in >> blockSize >> nextFortune;
    });
    
    // 显示网络问题
    connect(pshBtnNetError, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), [&](QLocalSocket::LocalSocketError socketError)
    {
        switch (socketError) {
        case QLocalSocket::ServerNotFoundError:
            break;
        case QLocalSocket::ConnectionRefusedError:
            break;
        case QLocalSocket::PeerClosedError:
            break;
        default:
        }
    });
}

QLocalServer端核心代码

Client::Client()
{
    QLocalServer* server = new QLocalServer(this);
    
    if (!server->listen("fortune")) 
    {
        return;
    }
    
    // 获取到来自客户端的一个新连接, 此段代码逻辑为: 客户端每个1s重新连接服务器,服务器每次接收到新连接后,向Peer对象发送数据,同时断开连接。迎接客户端的下一次连接。
    connect(server, &QLocalServer::newConnection, [&]()
    {
        QByteArray block;
        QDataStream out(&block, QIODevice::WriteOnly);
        out.setVersion(QDataStream::Qt_5_10);
        const int fortuneIndex = QRandomGenerator::global()->bounded(0, fortunes.size());
        const QString &message = fortunes.at(fortuneIndex);
        out << quint32(message.size());
        out << message;

        QLocalSocket *clientConnection = server->nextPendingConnection();
        connect(clientConnection, &QLocalSocket::disconnected,
                clientConnection, &QLocalSocket::deleteLater);
		
        clientConnection->write(block);
        clientConnection->flush();
        clientConnection->disconnectFromServer();
    });
    

}

应用场景

  1. 主程序与插件通信: 主程序作为服务器,插件作为客户端;
  2. 多进程协作 : 多个进程通过本地socket协调工作;
  3. 守护进程与服务 : 系统服务与GUI应用程序通信;
  4. 进程间数据共享 : 传输配置、状态信息等;
posted @ 2025-11-29 22:30  Hakuon  阅读(3)  评论(0)    收藏  举报