Qt中的QLocalSocket:本地套接字的应用

发布时间:2023-05-21

一、QLocalSocket简介

QLocalSocket是Qt的一种系统级套接字(socket),它允许使用本地文件名来创建一种专有协议,而不是使用网络地址和端口等信息来标识连接。通常情况下,QLocalSocket在同一台机器上的进程之间用于进行进程间通讯(Inter-Process Communication,IPC)。

二、QLocalSocket的基础使用

要使用QLocalSocket,首先需要创建一个对象(实例),其构造函数如下:

QLocalSocket(QObject* parent = nullptr)

在创建实例之后,需要调用connectToServer()函数来连接本地服务端,其原型如下:

void connectToServer(const QString& name, OpenMode openMode = ReadWrite);

其中,name参数表示要连接的本地服务端名字,openMode参数表示连接模式,它可以是ReadWriteReadOnly,默认值为ReadWrite。连接建立后,可以使用isWritable()函数判断是否可写,使用write()函数写入数据。 下面展示一个示例代码:

#include <QLocalSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
    QLocalSocket socket;
    socket.connectToServer("myserver");
    if (socket.waitForConnected()) {
        qDebug() << "Connected to server";
        socket.write("Hello server");
        if (socket.waitForBytesWritten())
            qDebug() << "Data written";
    } else {
        qDebug() << "Failed to connect to server";
    }
}

三、QLocalSocket的高级应用

1. 服务端示例

下面是一个服务端的示例代码,它创建了一个本地服务端并监听客户端发来的请求:

#include <QLocalServer>
#include <QLocalSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
    QLocalServer server;
    server.listen("myserver");
    while (server.isListening()) {
        if (server.waitForNewConnection()) {
            QLocalSocket* socket = server.nextPendingConnection();
            qDebug() << "Received connection:" << socket->peerName();
            QByteArray data = socket->readAll();
            qDebug() << "Data from client:" << data;
            socket->write("Hello client");
            socket->flush();
            socket->waitForBytesWritten();
            socket->waitForDisconnected();
            delete socket;
        }
    }
    return 0;
}

在这个示例中,服务端先调用listen()函数来创建一个本地服务端,同样使用了一个字符串“myserver”作为服务端的唯一标识。接着,服务端通过使用waitForNewConnection()函数等待新的客户端连接,并使用nextPendingConnection()函数获取客户端连接的QLocalSocket对象。之后,服务端读取客户端发来的数据并返回一个字符串“Hello client”。

2. 客户端示例

下面是一个客户端的示例代码,它连接到上面创建的负责监听的本地服务端并发送一个字符串“Hello server”,然后等待服务端返回数据:

#include <QLocalSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
    QLocalSocket socket;
    socket.connectToServer("myserver");
    if (socket.waitForConnected()) {
        qDebug() << "Connected to server";
        socket.write("Hello server");
        socket.flush();
        socket.waitForBytesWritten();
        socket.waitForReadyRead();
        qDebug() << "Data from server:" << socket.readAll();
        socket.disconnectFromServer();
    } else {
        qDebug() << "Failed to connect to server";
    }
    return 0;
}

在这个示例中,客户端使用connectToServer()函数连接到上面创建的服务端并发送一个字符串“Hello server”。 在向服务端发送数据后,需要通过flush()函数刷新缓冲区,然后通过waitForBytesWritten()函数等待写入数据完成。接着,使用waitForReadyRead()函数等待从服务端返回的数据,并使用readAll()函数获取数据内容。最后,客户端通过disconnectFromServer()函数断开连接。

四、QLocalSocket的应用场景

QLocalSocket用于同一台机器上进程间通讯是非常实用的,比如:服务端控制多个客户端的信息传递。它还可以作为调试工具,用于探测系统中正在运行的进程是否存在,并给它们发送消息。 下面展示一个示例代码,客户端向服务端发送特定的消息,从而通知服务端杀死指定的进程:

// 服务端代码
void killProcess(const QString& processName)
{
    QProcess process;
    process.start("pkill", QStringList() << processName);
}
int main(int argc, char *argv[])
{
    QLocalServer server;
    server.listen("myserver");
    while (server.isListening()) {
        if (server.waitForNewConnection()) {
            QLocalSocket* socket = server.nextPendingConnection();
            qDebug() << "Received connection:" << socket->peerName();
            QByteArray data = socket->readAll();
            if (data == "kill processX") {
                killProcess("processX");
            } else if (data == "kill processY") {
                killProcess("processY");
            }
            socket->disconnectFromServer();
            delete socket;
        }
    }
    return 0;
}
// 客户端代码
int main(int argc, char *argv[])
{
    QLocalSocket socket;
    socket.connectToServer("myserver");
    if (socket.waitForConnected()) {
        qDebug() << "Connected to server";
        socket.write("kill processX");
        socket.flush();
        socket.waitForBytesWritten();
        socket.disconnectFromServer();
    } else {
        qDebug() << "Failed to connect to server";
    }
    return 0;
}

在这个示例中,服务端监听客户端的连接,等待客户端发送的消息。如果客户端发送的消息为“kill processX”或“kill processY”,服务端就会用pkill命令杀死对应的进程。客户端连接到服务端后,发送一条命令“kill processX”给服务端,然后断开连接。

五、总结

QLocalSocket是Qt中用于实现本地套接字(socket)的类,它可以用于同一台机器上进程间通讯。使用QLocalSocket连接服务端可以通过调用connectToServer()函数,连接建立后可以通过write()函数写入数据。服务端通过等待新客户端连接并接收数据,可以使用listen()函数创建本地服务端并通过waitForNewConnection()函数等待新的客户端连接。 QLocalSocket在本地套接字的应用场景中使用广泛,它可以作为进程间通讯的工具,也可以作为调试工具来探测系统中运行的进程是否存在,并向它们发送消息。在实际开发过程中,可以根据应用需求选取合适的参数,利用QLocalSocket轻松实现进程间通讯。