Qt利用QLocalSocket和QLocalServer实现IPC

Posted ingy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt利用QLocalSocket和QLocalServer实现IPC相关的知识,希望对你有一定的参考价值。

QLocalServer提供了一种基于本地套接字的服务器,实现了接收本地socket的连接的功能。

通过调用listen()监听特定的连接,每次与client连接上时发出newConnection()信号。

通过调用nextPendingConnection()响应一个等待中的连接请求,返回一个指针,指向用于与client建立通信的QLocalSocket。

当连接发生错误时,serverError() 返回错误的类型,通过调用errorString()可以获取错误描述。

监听过程中,serverName()可获取当前服务器的名称。

调用close()停止对连接请求的监听。

虽然QLocalServer是为在事件循环中使用而设计出来的,但是在没有事件循环时也是可以使用的。没有事件循环时,你必须使用waitForNewConnection(),它只在以下两种情况下解除阻塞:1)有可用的连接;2)超时。

实例1:服务器

#ifndef SERVER_H
#define SERVER_H

#include <QWidget>
#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>

class CServer : public QObject
{
    Q_OBJECT

public:
    CServer() : m_server(NULL)
    {
        m_server = new QLocalServer;
        connect(m_server, SIGNAL(newConnection()), SLOT(serverNewConnectionHandler()));
    }

    ~CServer()
    {
        m_server->close();
        delete m_server;
    }

    void RunServer()
    {
        qDebug() << "Run Server ok";

        QLocalServer::removeServer("ServerName");
        bool ok = m_server->listen("ServerName");
        if (!ok)
        {
            // TODO:
        }
    }

private slots:
    void serverNewConnectionHandler()
    {
        qDebug() << "New Connection";
        qDebug() << "listen: " << m_server->serverName();

        QLocalSocket* socket = m_server->nextPendingConnection();
        connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyReadHandler()));
        connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
    }

    void socketReadyReadHandler()
    {
        QLocalSocket* socket = static_cast<QLocalSocket*>(sender());
        if (socket)
        {
            QTextStream stream(socket);
            qDebug() << "Read Data From Client:" << stream.readAll();

            QString response = "Hello Client";
            socket->write(response.toUtf8());
            socket->flush();
        }
        // 返回到客户端的void sendMessage 方法,m_socket->waitForReadyRead()之后的操作
    }

private:
    QLocalServer *m_server;

};

#endif // SERVER_H

#include "server.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    CServer server;
    server.RunServer();

    return a.exec();
}

 

QLocalSocket继承自QIODevice,提供了一种本地套接字,在Windows系统中其实是一种有名管道,在Unix中是一种本地套接字。

socketError()返回套接字连接错误类型,errorString()返回错误详细描述。

也可以在没有事件循环的情况下工作,waitForConnected(),waitForReadyRead(),waitForBytesWritten()和waitForDisconnected()用于阻塞等待事件的到来,知道事件到来或者超时。

实例2:客户端

#ifndef CLIENT_H
#define CLIENT_H

#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>

class CClient : public QObject
{
    Q_OBJECT

public:
    CClient() : m_socket(NULL)
    {
        m_socket = new QLocalSocket();

        connect(m_socket, SIGNAL(connected()), SLOT(socketConnectedHandler()));
        connect(m_socket, SIGNAL(disconnected()), SLOT(socketDisConnectedHandler()));
        connect(m_socket, SIGNAL(error(QLocalSocket::LocalSocketError)), SLOT(socketErrorHandler(QLocalSocket::LocalSocketError)));
    }

    ~CClient()
    {
        m_socket->disconnectFromServer();
        delete m_socket;
    }

public:
    void ConnectToServer(const QString &strServerName)
    {
        // serverNewConnectionHandler 成员方法将被调用
        m_socket->connectToServer(strServerName);
        if (m_socket->waitForConnected())
        {
            // TODO:
        }
    }

    void sendMessage(const QString &msg)
    {
        m_socket->write(msg.toStdString().c_str());
        m_socket->flush();

        if (!m_socket->bytesAvailable())
            m_socket->waitForReadyRead();

        QTextStream stream(m_socket);
        QString respond = stream.readAll();
        qDebug() << "Read Data From Server:" << respond;
    }

private slots:
    void socketConnectedHandler()
    {
        qDebug() << "connected.";
    }


    void socketDisConnectedHandler()
    {
        qDebug() << "disconnected.";
    }

    void socketErrorHandler(QLocalSocket::LocalSocketError error)
    {
        qWarning() << error;
    }

private:
    QLocalSocket *m_socket;

};

#endif // CLIENT_H

#include "client.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    CClient client;
    client.ConnectToServer("ServerName");

    client.sendMessage("Hellow Server");

    return a.exec();
}

 

以上是关于Qt利用QLocalSocket和QLocalServer实现IPC的主要内容,如果未能解决你的问题,请参考以下文章

Qt基础之二十:进程间通信

IPC QLocalSocket -> C,为啥我的连接失败?连接失败:[2](没有这样的文件?!)

Qt IPC - 命名管道

如何在使用 QLocalSocket 的 IPC 期间告诉客户端已经结束连接?

qt浏览器插件中的IPC

从 QLocalSocket 读取超过 2048 个字节