Qt QLocalSocket 进程间通信(QLocalServer)

简述

QIODevice
做为QLocalSocket的父类,我们先做一下简单的介绍
QIODevice类是Qt中所有输入/输出设备的基本接口类。
QIODevice为支持读取和写入数据块的设备提供了一个通用的实现和一个抽象接口,比如QFile、QBuffer和QTcpSocket。QIODevice是抽象的,不能被实例化。
在访问设备之前,必须调用open()来设置正确的OpenMode(如ReadOnly或ReadWrite)。然后,您可以用write()或putChar()来写入数据,并通过调用read()、readLine()或readAll()来读取。当您使用完该设备时,调用close()。
QIODevice区分了两种类型的设备:随机访问设备和顺序设备。
随机访问设备支持使用seek()寻求任意位置。文件中的当前位置可以通过调用pos()来获得。QFile和QBuffer都是随机访问设备的例子。
顺序设备不支持任意位置。数据必须一次读取。pos()和size()的函数不适用于连续的设备。QTcpSocket和QProcess是连续设备的例子。
您可以使用isSequential()来确定设备的类型
当新数据可用时,QIODevice会发出readyRead();例如,如果新数据已经到达网络,或者附加的数据被追加到您正在阅读的文件中。您可以调用bytesAvailable()来确定当前可供阅读的字节数。在使用诸如QTcpSocket这样的异步设备进行编程时,使用tesavailable()和readyRead()信号是很常见的,在这种情况下,数据片段可以在任意时间点到达。QIODevice会在每次将数据的有效负载写入设备时发出bytesWritten()信号。使用bytesToWrite()来确定要写入的当前数据量。
QIODevice的某些子类,如QTcpSocket和QProcess,是异步的。这意味着诸如write()或read()之类的输入输出函数总是立即返回,而与设备本身的通信可能发生在控制返回到事件环路时。QIODevice提供了一些功能,允许您立即执行这些操作,同时阻塞调用线程,并且不进入事件循环。这使得QIODevice子类无需事件循环,也可以在单独的线程中使用:
waitForReadyRead()-这个函数在调用线程中挂起操作,直到有新的数据可用为止。
waitForBytesWritten()-这个函数在调用线程中挂起操作,直到将一个数据有效负载写入设备为止。
waitFor...()——QIODevice的子类实现针对特定设备的操作的阻塞功能。例如,QProcess有一个名为waitForStarted()的函数,该函数在调用线程中挂起操作,直到进程启动为止。

QLocalSocket类提供了一个本地socket。

在Windows中,这是一个命名管道;在Unix中,这是一个本地网域socket

如果发生错误,socketError()会返回错误的类型,errorString()则返回人类可读的错误描述。

虽然QLocalSocket是一个事件循环使用而设计,它也可以不被如此使用。这种情况下,必须使用 
waitForConnected()、waitForReadyRead()、waitForBytesWritten()、和waitForDisconnected()来进行阻塞,直到操作完成或超时。

成员类型文档

枚举 QLocalSocket::LocalSocketError

LocalServerError枚举代表了可能发生的错误,最近的错误可以通过调用QLocalSocket::error()来获取。

常量描述
QLocalSocket::ConnectionRefusedErrorQAbstractSocket::ConnectionRefusedError连接被对方拒绝(或超时)
QLocalSocket::PeerClosedErrorQAbstractSocket::RemoteHostClosedError远程socket关闭了连接。请注意,在远程关闭通知发送后,client socket(即,这个socket)将关闭。
QLocalSocket::ServerNotFoundErrorQAbstractSocket::HostNotFoundError本地socket名字没有被发现
QLocalSocket::SocketAccessErrorQAbstractSocket::SocketAccessErrorsocket操作失败,因为应用程序缺乏必要的特权。
QLocalSocket::SocketResourceErrorQAbstractSocket::SocketResourceError本地系统超出资源(例如:太多的socket)
QLocalSocket::SocketTimeoutErrorQAbstractSocket::SocketTimeoutErrorsocket操作超时。
QLocalSocket::DatagramTooLargeErrorQAbstractSocket::DatagramTooLargeError数据报比操作系统的限制(可低至8192字节)大。
QLocalSocket::ConnectionErrorQAbstractSocket::NetworkError连接时发生错误
QLocalSocket::UnsupportedSocketOperationErrorQAbstractSocket::UnsupportedSocketOperationError本地操作系统不支持请求的socket操作
QLocalSocket::OperationErrorQAbstractSocket::OperationError当socket在一个不允许它的状态中时,试图进行操作。
QLocalSocket::UnknownSocketErrorQAbstractSocket::UnknownSocketError发生无法识别的错误

 

枚举 QLocalSocket::LocalSocketState

这个枚举描述一个套接字的不同状态。

常量描述
QLocalSocket::UnconnectedStateQAbstractSocket::UnconnectedStatesocket未连接
QLocalSocket::ConnectingStateQAbstractSocket::ConnectingStatesocket已开始建立连接
QLocalSocket::ConnectedStateQAbstractSocket::ConnectedState建立连接
QLocalSocket::ClosingStateQAbstractSocket::ClosingStatesocket即将关闭(数据仍可以等待写入)

Public函数

void abort()

终止当前连接,并重置socket。与disconnectFromServer()不同,此函数会立即关闭socket,并且清除掉写缓冲区中未处理的数据。

void connectToServer(OpenMode openMode = ReadWrite)

尝试创建一个到serverName()的连接。在打开连接之前必须调用setServerName();或者可以使用connectToServer(const QString &name, OpenMode openMode)。

以指定的openMode打开socket,首先进入ConnectingState,如果建立了连接,QLocalSocket进入ConnectedState,并发射connected()信号。

调用此函数后,当发生错误时,socket会发射error()信号。

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

重载函数

void disconnectFromServer()

尝试关闭socket。如果缓冲区中仍有等待写入的数据,QLocalSocket将进入ClosingState状态,然后等待,直到所有数据写完。最终,QLocalSocket进入UnconnectedState状态,发射disconnectedFromServer()信号。

LocalSocketError error() const

返回最后发生的错误类型。

bool flush()

此函数能够无阻塞地将内部写缓冲区中的数据尽可能多的写入到socket中。当有任何数据被写入时,返回true;否则返回false。 
当需要QLocalSocket立即发送缓冲区中的数据时,可以调用此函数。成功写入的字节数取决于操作系统。在大多数情况下,不需要调用该函数,因为一旦事件循环得到了控制权之后,QLocalSocket就会自动的开始发送数据。当没有事件循环时,调用waitForBytesWritten()代替。

QString fullServerName() const

返回socket连接到的server path。

注意:返回值因操作系统不同存在差异。

bool isValid() const

如果socket是有效的并且并且可以使用了,返回ture;否则返回false。

注意: socket进行读/写之前,一定是处于ConnectedState状态。

qint64 readBufferSize() const

返回内部读取缓冲区的大小。在调用read()或readAll()之前,这限制了client接收的数据量。读缓冲区大小为0(默认)意味着缓冲区没有大小限制,确保没有数据丢失。

QString serverName() const

返回由setServerName()指定的server的name。如果没有调用setServerName(),或者connectToServer()失败,返回空字符串。

void setReadBufferSize(qint64 size)

设置QLocalSocket内部读缓冲区的大小为size个字节。

如果缓冲区被限制为一定的大小,QLocalSocket不会缓冲超过这个数据的大小。

如果设置了指定的size,QLocalSocket最多只能缓存该size大小的数据。特殊地,大小为0的缓冲区意味着读缓冲区是无限的,并且所有传入数据都会得到缓冲,这是默认的。

如果你只在特定的时间点(例如:在一个实时流媒体应用程序)读数据,或者想保护你的socket避免接收太多的数据(这最终可能会导致应用程序耗尽内存),这个选项是有用的。

void setServerName(const QString &name)

设置对等连接的名称。在Windows中,名字是命名管道的名称;在Unix中,名称是本地域socket的名称。 
当未连接socket时,此函数必须被调用。

bool setSocketDescriptor(qintptr socketDescriptor, LocalSocketState socketState = ConnectedState, OpenMode openMode = ReadWrite)

使用本地socket描述符socketDescriptor完成QLocalSocket的初始化。如果socketDescriptor被接受为一个有效的socket描述符,返回true;否则返回false。socket被以指定的模式openMode打开,并进入socketState指定的socket状态。

注意:无法使用相同的本地socket描述符来初始化两个本地socket。

qintptr socketDescriptor() const

如果可用,返回QLocalSocket对象的本地socket描述符。否则,返回-1。

当QLocalSocket处于UnconnectedState状态时,socket描述符无效。

LocalSocketState state() const

返回socket的状态。

bool waitForConnected(int msecs = 30000)

等待,直到socket连接。直到msecs毫秒。如果连接已建立,返回true;否则返回false。返回false时,可以调用error()来确定错误的原因。

下面的例子最多等待1秒来建立连接:

  1. socket->connectToServer("market");

  2. if (socket->waitForConnected(1000))

  3. qDebug("Connected!");

如果msecs是-1,该函数不会超时。

bool waitForDisconnected(int msecs = 30000)

等待,直到socket断开。直到msecs毫秒。如果连接已断开,返回true;否则返回false。返回false时,可以调用error()来确定错误的原因。

下面的例子最多等待1秒来断开连接:

  1. socket->disconnectFromServer();

  2. if (socket->waitForDisconnected(1000))

  3. qDebug("Disconnected!");

如果msecs是-1,该函数不会超时。

信号

void connected()

调用connectToServer()之后,并且成功建立连接,发射此信号。

void disconnected()

当socket已经断开连接,发射此信号。

void error(QLocalSocket::LocalSocketError socketError)

当有错误发生时,会发射此信号。参数socketError表明发生错误的类型。

QLocalSocket::LocalSocketError不是一个注册的metatype,所以在queued connections时,需要使用Q_DECLARE_METATYPE()和qRegisterMetaType()注册它。

**注意:**error是这个类的一个重载信号。要连接这个信号,需要使用函数指针语法,必须在static_cast中指定信号类型,如本例所示:

connect(localSocket, static_cast<void(QLocalSocket::*)(QLocalSocket::LocalSocketError)>(&QLocalSocket::error), [=](QLocalSocket::LocalSocketError socketError){ /* ... */ });
  • 1

void stateChanged(QLocalSocket::LocalSocketState socketState)

当QLocalSocket的状态改变时,发射此信号。参数socketState是新状态。

QLocalSocket::SocketState不是一个注册的metatype,所以在queued connections时,需要使用Q_DECLARE_METATYPE()和qRegisterMetaType()注册它。

重新实现的Public函数

[virtual] qint64 bytesAvailable() const

重新实现QIODevice::bytesAvailable()。

[virtual] qint64 bytesToWrite() const

重新实现QIODevice::bytesToWrite()。

[virtual] bool canReadLine() const

重新实现QIODevice::canReadLine()。

[virtual] void close()

重新实现QIODevice::close()。

[virtual] bool isSequential() const

重新实现QIODevice::isSequential()。

[virtual] bool waitForBytesWritten(int msecs = 30000)

重新实现QIODevice::waitForBytesWritten()。

[virtual] bool waitForReadyRead(int msecs = 30000)

重新实现QIODevice::waitForReadyRead()。

此函数阻塞,直到数据可供阅读并且readyRead()信号被发射。在msecs毫秒后,就会超时;默认的超时时间为30000毫秒。

如果数据可供阅读,该函数返回true;否则返回false(如果发生错误或操作超时)。

[virtual] bool open(OpenMode openMode = ReadWrite)

重新实现QIODevice::open()。

相当于connectToServer(OpenMode mode),以指定的openMode打开socket至setServerName()定义的server。

注意:不像其他大多数的QIODevice子类,open()可以不直接打开设备。如果socket已连接或server连接到没有定义,该函数返回false,其他情况返回true。一旦设备打开(或连接失败),就会发射信号connected()或error()。

重新实现的Protected函数

qint64 readData(char *data, qint64 c)

重新实现QIODevice::readData()。

qint64 writeData(const char *data, qint64 c)

重新实现QIODevice::writeData()。

以下参考:https://blog.csdn.net/u013189731/article/details/39155141

QLocalServer

继承自QObject。

QLocalServer提供了一个基于本地套接字(socket)的服务端(server)。
QLocalServer可以接受来自本地socket的连接。
server通过调用listen(),监听特定的连接。
newConnection()是在每次server与client连接上时所发出的信号。
nextPendingConnection()将等待中的连接当作一个已连接上的QLocalSocket。返回值是指向QLocalSocket的指针,这个QLocalSocket可以与client建立通信。
当发生错误时,serverError() 返回错误的类型,调用errorString()可以获取对错误的描述。
在监听过程中,通过 serverName()可以获取当前server监听的名称。
close()使QLocalServer停止对连接请求的监听。
虽然QLocalServer是为在事件循环中使用而设计出来的,但是在没有事件循环时也是可以使用的。没有事件循环时,你必须使用waitForNewConnection(),它只在以下两种情况下解除阻塞:1)有可用的连接;2)超时。

 

1. 建立一个QLocalServer实例 m_server

2. 进行listen :                         

 

 m_server->listen("servername")

3. 当有连接到来时,QLocalServer会发送netConnection()信号,所以进行信号连接, 在init()函数中:

 

  connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));

4.在newConnection()函数中取得连接客户端的QLocalSocket

 

QLocalSocket *newsocket = m_server->nextPendingConnection();

 

5.当QLocalSocket可以读数据时它会发送readyRead()信号,所以对newsocket进行信号连接, 在newConnection()函数中:

 

 connect(newsocket, SIGNAL(readyRead()), this, SLOT(readyRead()));

6.在readyRead()函数中读取数据:

 
// 取得是哪个localsocket可以读数据了
        QLocalSocket *local = static_cast<QLocalSocket *>(sender()); 
        if (!local)
            return;
        QTextStream in(local);
        QString     readMsg;
        // 读出数据
        readMsg = in.readAll();

全部代码, server端:

 

 

// server.h

/

#ifndef SERVER_H
#define SERVER_H
 
#include <QLocalServer>
#include <QLocalSocket>
 
class Server : public QObject
{
    Q_OBJECT
public:
    Server()
    {
        m_server = 0;
    } 
    ~Server()
    {
        if (m_server) 
        {
            delete m_server;
        }
    }
 
    int init(const QString & servername)
    {
        // 如果已经有一个实例在运行了就返回0
        if (isServerRun(servername)) {
            return 0;
        }
        m_server = new QLocalServer;
 
// 先移除原来存在的,如果不移除那么如果
        // servername已经存在就会listen失败
        QLocalServer::removeServer(servername);
        // 进行监听
        m_server->listen(servername);
        connect(m_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
        return 1;
    }
private slots:
    // 有新的连接来了
    void newConnection()
    {
        QLocalSocket *newsocket = m_server->nextPendingConnection(); 
        connect(newsocket, SIGNAL(readyRead()), this, SLOT(readyRead()));
    }  
    // 可以读数据了
    void readyRead()
    {
        // 取得是哪个localsocket可以读数据了
        QLocalSocket *local = static_cast<QLocalSocket *>(sender()); 
        if (!local)
            return;
        QTextStream in(local);
        QString     readMsg;
        // 读出数据
        readMsg = in.readAll();
        // 发送收到数据信号
        emit newMessage(readMsg);
    }
private:
    // 判断是否有一个同名的服务器在运行
    int isServerRun(const QString & servername)
    {
        // 用一个localsocket去连一下,如果能连上就说明
        // 有一个在运行了
        QLocalSocket ls;
        ls.connectToServer(servername);
        if (ls.waitForConnected(1000)){
            // 说明已经在运行了 
            ls.disconnectFromServer();
            ls.close();
            return 1;
        }
        return 0;
    }
signals:
    void newMessage(const QString &msg);
private:
    QLocalServer *m_server;
};
#endif // SERVER_H
///
/// main.cpp
///
 
#include <QApplication>
#include <QLabel>
#include <QMessageBox>
#include "server.h"
 
int main(int argc, char **argv)
{
    QApplication app(argc, argv);
    QLabel       text("teststts");
    Server       s;
    if (!s.init("localserver-test")){
        // 初使化失败, 说明已经有一个在运行了
        QMessageBox::information(&text, "info", "There is already exist one!"); 
        return 1;
    }
    QObject::connect(&s, SIGNAL(newMessage(const QString &)),&text, SLOT(setText(const QString &)));
    text.show();
    return app.exec();
}

 

用于测试的客户端代码, 每一秒向server发送一个随机数:

 
 

 

#include <QLocalSocket>
#include <stdlib.h>
#include <unistd.h>
 
int main(int argc, char **argv)
{
    QLocalSocket ls;
    ls.connectToServer("localserver-test");
    srandom(1000);
    if (ls.waitForConnected()){
        while (1){
            QTextStream ts(&ls);
            ts << QString::number(random()) + "\nTTTTTTTTTT" + "\nXXXXXXXX";
            ts.flush();
            ls.waitForBytesWritten();
            sleep(1);
        }
    }
    return 0;
}

 

 

先运行server程序,然后运行测试用的客户端...

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Qt中的QLocalSocket是一种用于进程间通信的组件。它允许不同的进程在同一台计算机上进行通信,通过该组件可以实现进程之间的数据交换和信息传递。 QLocalSocketQt的网络类之一,它继承自QTcpSocket类,用于在本地主机上建立起客户端-服务器类型的连接。使用QLocalSocket进行进程间通信的基本步骤如下: 首先,创建一个QLocalSocket对象,并调用connectToServer()函数连接到目标进程的服务器端。在目标进程中,需要创建一个QLocalServer对象并调用其listen()函数来创建服务器端。 然后,通过write()函数向服务器端发送需要传递的数据。服务器端可以通过继承QLocalServer并重载incomingConnection()函数来接收客户端的连接请求,并使用read()函数读取来自客户端的数据。 QLocalSocket还提供了readyRead()信号,用于在客户端接收到数据时触发相应的槽函数进行处理。同时,error()信号可以用来捕获任何连接错误。 当数据传递完成后,可以调用disconnectFromServer()函数来断开客户端与服务器端之间的连接。 总之,Qt的QLocalSocket组件提供了一种方便和简单的方式实现进程间通信。通过使用QLocalSocket,不同进程之间可以直接交换数据和信息,实现一些特定的功能,提高了应用程序的灵活性和可扩展性。 ### 回答2: Qt中的QLocalSocket类可用于进程间通信进程间通信是指两个或多个不同的进程之间交换数据或消息的过程。在Qt中,可以使用QLocalSocket类在本地主机上的进程间建立通信。 QLocalSocket是一个套接字(Socket)类,它可以在本地主机上的不同进程之间建立双向通信。要使用QLocalSocket进行进程间通信,首先需要创建一个QLocalServer对象作为服务器端,等待其他进程连接。然后在客户端进程中,创建一个QLocalSocket对象,用于与服务器端建立连接。 服务器端代码示例: ```cpp QLocalServer server; if (!server.listen("myApp")) { // 服务器启动失败 return; } // 服务器等待连接 QLocalSocket *socket = server.nextPendingConnection(); if (!socket) { // 连接失败 return; } // 接收数据 QObject::connect(socket, &QLocalSocket::readyRead, [&socket]() { QByteArray data = socket->readAll(); // 处理接收到的数据 }); // 发送数据给客户端 QByteArray sendData = "Hello from server"; socket->write(sendData); ``` 客户端代码示例: ```cpp QLocalSocket socket; socket.connectToServer("myApp"); // 检查连接状态 if (socket.state() != QLocalSocket::ConnectedState) { // 连接失败 return; } // 发送数据给服务器端 QByteArray sendData = "Hello from client"; socket.write(sendData); // 接收服务器端发来的数据 QObject::connect(&socket, &QLocalSocket::readyRead, [&socket]() { QByteArray data = socket.readAll(); // 处理接收到的数据 }); ``` 以上示例代码演示了一个基本的QLocalSocket进程间通信的过程。服务器端创建QLocalServer对象并等待连接,客户端连接到服务器端并发送数据。服务器端收到数据后进行处理,然后发送数据给客户端。客户端接收到服务器端发送的数据后进行处理。 总而言之,使用QLocalSocket类可以实现方便的进程间通信,方便不同进程之间的数据交换和消息传递。 ### 回答3: qt的QLocalSocket类是一个用于进程间通信的工具。进程间通信是指不同进程之间进行交流和数据传输的过程。 QLocalSocket通过本地套接字(Local Socket)来实现进程间通信。本地套接字是一种特殊的套接字类型,它允许在同一台机器上的不同进程之间进行通信,而不需要经过网络。 使用QLocalSocket进行进程间通信的基本步骤如下: 1. 创建一个QLocalServer对象,用于监听连接请求。本地服务器类(QLocalServer)提供了一种在本地环境中创建服务器的方法。 2. 创建一个QLocalSocket对象,用于与服务端建立连接。本地套接字类(QLocalSocket)提供了一种在本地环境中创建套接字的方法。 3. 在服务端,接受连接请求并建立连接。当服务端收到一个连接请求时,可以使用QLocalServer的nextPendingConnection()方法接受请求并返回一个QLocalSocket对象,用于进一步的通信。 4. 在客户端,连接到服务端。客户端使用QLocalSocket的connectToServer()方法来连接到服务端。 5. 通过QLocalSocket对象进行数据传输。一旦连接建立,就可以使用QLocalSocket的write()方法向对方发送数据,使用read()方法读取对方发送的数据。 QLocalSocket具有很多特性,例如支持阻塞和非阻塞的通信方式、支持对错误进行处理、支持多线程等。通过使用QLocalSocket,我们可以方便地在同一台机器上的不同进程之间进行通信,实现进程间的数据传输和交流。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值