Qt之进程间通信(TCP/IP)

简介:

简述

可以通过Qt提供的IPC使用TCP/IP,使用QtNetwork模块即可实现,TCP/IP在实现应用程序和进程内部通信或与远程进程间的通信方面非常有用。

QtNetwork模块提供的类能够创建基于TCP/IP的客户端与服务端应用程序。为实现底层的网络访问,可以使用QTcpSocket、QTcpServer和QUdpSocket,并提供底层网络类。还提供了使用常规协议实现网络操作的QNetworkRequest、QNetworkReply、QNetworkAccessManager。

QtNetwork

作为使用IPC的方法,TCP/IP可以使用多种类进行进程内部和外部的通信。

QtNetwork模块提供的类:

说明
QLocalServer 基于服务器的本地套接字的类
QLocalSocket 支持本地套接字的类
QNetworkAccessManager 处理从网络首发收据响应的类
QSocketNotifier 监控从网络通知消息的类
QSsl 在所有网络通信上用于SSL认证的类
QSslSocket 支持通过客户端和服务器端加密的套接字的类
QTcpServer 基于TCP的服务器端类
QTcpSocket TCP套接字
QUdpSocket UDP套接字

除表中所示,Qt提供的QtNetwork模块还支持多种协议。如果需要实现内部进程间的通信,建议使用QLocalSocket类。

下面我们来看一个示例,可以在Creator自带的示例中查找QLocalSocket或Local Fortune。

Server

首先,启动Server,这是必然的,服务端不开启,客户端怎么连接得上呢?

server = new QLocalServer(this);

// 告诉服务器监听传入连接的名字。如果服务器当前正在监听,那么将返回false。监听成功返回true,否则为false
if (!server->listen("fortune")) {
    QMessageBox::critical(this, tr("Fortune Server"),
                        tr("Unable to start the server: %1.")
                        .arg(server->errorString()));
    close();
    return;
}

fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
         << tr("You've got to think about tomorrow.")
         << tr("You will be surprised by a loud noise.")
         << tr("You will feel hungry again in another hour.")
         << tr("You might have mail.")
         << tr("You cannot kill time without injuring eternity.")
         << tr("Computers are not intelligent. They only think they are.");

// 有新客户端进行连接时,发送数据
connect(server, SIGNAL(newConnection()), this, SLOT(sendFortune()));

// 发送数据
void Server::sendFortune()
{
    // 从fortunes中随机取出一段字符串然后进行写入。
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);
    out << (quint16)0;
    out << fortunes.at(qrand() % fortunes.size());
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    // nextPendingConnection()可以返回下一个挂起的连接作为一个连接的QLocalSocket对象。
    QLocalSocket *clientConnection = server->nextPendingConnection();
    connect(clientConnection, SIGNAL(disconnected()),
            clientConnection, SLOT(deleteLater()));

    clientConnection->write(block);
    clientConnection->flush();
    clientConnection->disconnectFromServer();
}

socket被当做server的孩子创建,这意味着,当QLocalServer对象被销毁时它也会被自动删除。这明显是一个删除对象的好主意,使用完成以后,避免了内存的浪费。

Client

启动客户端,连接到对应的服务器,如果连接不上,则进行错误处理。

socket = new QLocalSocket(this);

connect(getFortuneButton, SIGNAL(clicked()),
        this, SLOT(requestNewFortune()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readFortune()));
connect(socket, SIGNAL(error(QLocalSocket::LocalSocketError)),
        this, SLOT(displayError(QLocalSocket::LocalSocketError)));

// 连接到服务器,abort()断开当前连接,重置socket。
void Client::requestNewFortune()
{
    getFortuneButton->setEnabled(false);
    blockSize = 0;
    socket->abort();
    socket->connectToServer(hostLineEdit->text());
}

// 读取服务器端发送的数据
void Client::readFortune()
{
    // 读取接收到的数据
    QDataStream in(socket);
    in.setVersion(QDataStream::Qt_4_0);

    if (blockSize == 0) {
        if (socket->bytesAvailable() < (int)sizeof(quint16))
            return;
        in >> blockSize;
    }

    if (in.atEnd())
        return;

    QString nextFortune;
    in >> nextFortune;

    // 如果当前的数据和收到的数据相同,则重新请求一次,因为是随机的字符串,所以肯定不会每次都相同。
    if (nextFortune == currentFortune) {
        QTimer::singleShot(0, this, SLOT(requestNewFortune()));
        return;
    }

    currentFortune = nextFortune;
    statusLabel->setText(currentFortune);
    getFortuneButton->setEnabled(true);
}

// 发生错误时,进行错误处理
void Client::displayError(QLocalSocket::LocalSocketError socketError)
{
    switch (socketError) {
    case QLocalSocket::ServerNotFoundError:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The host was not found. Please check the "
                                    "host name and port settings."));
        break;
    case QLocalSocket::ConnectionRefusedError:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The connection was refused by the peer. "
                                    "Make sure the fortune server is running, "
                                    "and check that the host name and port "
                                    "settings are correct."));
        break;
    case QLocalSocket::PeerClosedError:
        break;
    default:
        QMessageBox::information(this, tr("Fortune Client"),
                                 tr("The following error occurred: %1.")
                                 .arg(socket->errorString()));
    }

    getFortuneButton->setEnabled(true);
}
相关文章
|
2月前
|
编译器 C++ 开发者
QT基础【7-跨进程发送信号】
QT基础【7-跨进程发送信号】
|
2月前
|
运维 监控 网络协议
QT实现TCP通信:从基础到高级的全面解析
QT实现TCP通信:从基础到高级的全面解析
198 0
|
编解码 C++ Windows
QT软件开发: QProcess启动进程完成交互并获取输出
QT软件开发: QProcess启动进程完成交互并获取输出
2024 0
QT软件开发: QProcess启动进程完成交互并获取输出
|
1月前
|
监控 C++
C++ Qt开发:QProcess进程管理模块
Qt是一个跨平台的C++图形库,简化了窗体应用开发,支持通过拖放组件提升效率。本章节关注`QProcess`组件,它用于控制和管理进程,例如执行命令、运行可执行文件及与外部进程通信。`QProcess`提供多种方法如`start`、`waitForStarted`和`waitForFinished`等,实现启动、监控和交互。示例展示了如何使用`QProcess`获取系统进程和信息,通过`tasklist`和`systeminfo`命令,并将结果展示在`QTreeWidget`中。
28 0
C++ Qt开发:QProcess进程管理模块
|
1月前
|
网络协议 编译器 调度
【Qt 面试题】深入剖析QT TCP通讯流程及应用实例
【Qt 面试题】深入剖析QT TCP通讯流程及应用实例
30 0
|
3月前
|
网络协议
Qt Tcp Server
Qt Tcp Server
20 0
|
4月前
|
Linux
QT中进程的创建
QT中进程的创建
29 0
|
7月前
|
网络协议 C++ Python
Qt+C++ TCP发送接收信息客户端与服务端窗体
Qt+C++ TCP发送接收信息客户端与服务端窗体
66 0
Qt+C++ TCP发送接收信息客户端与服务端窗体
|
10月前
Qt通过QProcess启动进程并传递命令行参数
Qt通过QProcess启动进程并传递命令行参数
458 0
|
程序员 C++ Windows
Qt多线程分享——你必须知道的进程知识点
Qt多线程分享——你必须知道的进程知识点

相关实验场景

更多

推荐镜像

更多