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

简介: 简述可以通过Qt提供的IPC使用TCP/IP,使用QtNetwork模块即可实现,TCP/IP在实现应用程序和进程内部通信或与远程进程间的通信方面非常有用。QtNetwork模块提供的类能够创建基于TCP/IP的客户端与服务端应用程序。为实现底层的网络访问,可以使用QTcpSocket、QTcpServer和QUdpSocket,并提供底层网络类。还提供了使用常规协议

简述

可以通过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);
}

更多参考

目录
相关文章
|
网络协议
TCP/IP协议的介绍
TCP/IP协议是众多协议的统称,通过分层结构来管理。可分为七层模型或四层结构
|
网络协议 网络架构
六、TCP/IP模型 和 5层参考模型
六、TCP/IP模型 和 5层参考模型
六、TCP/IP模型 和 5层参考模型
|
域名解析 网络协议
IP协议, TCP协议 和DNS 服务分别是干什么的?
大家好,我是阿萨。昨天讲解了网络四层协议[TCP/IP协议族分为哪4层?]今天我们学习下IP 协议, TCP 协议和DNS 协议分别是干什么的。
210 0
IP协议, TCP协议 和DNS 服务分别是干什么的?
|
网络协议
TCP/IP协议族有哪些?
大家好,我是阿萨。昨天我们学习了[URI 和URL 的区别是什么?]了解了URI 和URL的区别。 学习HTTP, 绕不开TCP/IP,那么TCP/IP 协议族分为哪4层?
254 0
TCP/IP协议族有哪些?
|
网络协议 网络性能优化 网络安全
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(2)
|
域名解析 网络协议 安全
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
网络协议报文理解刨析篇二(再谈Http和Https), 加上TCP/UDP/IP协议分析(理解着学习), 面试官都惊讶你对网络的见解(1)
|
网络协议 算法 网络性能优化
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
网络入门基础模型, 网络大体框架, TCP/IP协议栈, 各种局域网和广域网刨析 (以图解的方式推开网络大门)
|
存储 运维 网络协议
深入浅出:这次终于能把 TCP/IP 协议搞明白了
深入浅出:这次终于能把 TCP/IP 协议搞明白了
深入浅出:这次终于能把 TCP/IP 协议搞明白了
|
网络协议 NoSQL 数据库连接
【七日打卡】TCP&IP在开发中的作用
在网络应用开发中, 程序之间的交互都是通过TCP连接来进行通信的, 比如数据库连接, 事务连接管理。
【七日打卡】TCP&IP在开发中的作用
|
网络协议
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。
ACK的累加规则-wireshark抓包分析-不包含tcp头部、ip头部、数据链路层头部等。