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

简述

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

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

下面我们来看一个示例,是基于QTcpSocket、QTcpServer类的一个小demo。

服务器(Server)

#include "myserversocket.h"
#include "ui_myserversocket.h"

MyServerSocket::MyServerSocket(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyServerSocket)
{
    ui->setupUi(this);

    // 第一步:创建QTcpServer对象
    m_pTcpServer = new QTcpServer();

    // 第三步:当服务器被客户端访问时,会发出newConect()信号.
    // 因此,为该信号添加槽函数,并用一个QTcpSocket对象接收客户端访问
    connect(m_pTcpServer, &QTcpServer::newConnection, this, &MyServerSocket::slotNewConnect);

    // 设置默认IP和端口port
    ui->lineEdit_IP->setText("192.168.0.2");
    ui->lineEdit_Port->setText("8888");
}

MyServerSocket::~MyServerSocket()
{
    // 取消监听
    m_pTcpServer->close();
    m_pTcpServer->deleteLater();
    delete ui;
}

// 监听槽函数
void MyServerSocket::slotListen()
{
    // 第二步:侦听一个端口,客户端可以使用这个端口访问服务器
    QHostAddress IP(ui->lineEdit_IP->text());
    qint16 port = ui->lineEdit_Port->text().toInt();

    if (m_pTcpServer->listen(IP, port))
    {
        // 监听成功
    }
    else
    {
        // 监听失败
        QMessageBox::warning(this, "warning", tr("监听失败!"),
                             QMessageBox::Yes, QMessageBox::No);
    }
}

void MyServerSocket::slotSend()
{
    // 第四步:使用m_pTcpSocket的write函数向客户端发送数据
    //发送socket数据包
    qint64 writeResult = m_pTcpSocket->write(ui->textEdit_Send->toPlainText().toLatin1());
    //从缓冲区读写数据,如果从缓冲区读写了数据,则返回true。没有数据读写,则返回false
    bool bFlush = m_pTcpSocket->flush();

    if (writeResult!=-1 && bFlush==1)
    {
        //返回值不为-1,则发送数据包成功
        if(writeResult==0)
        {
            QMessageBox::warning(this, "warning", tr("写数据结果返回值为0"),
                                 QMessageBox::Yes, QMessageBox::No);
        }
        QMessageBox::warning(this, "warning", tr("写数据成功!%1").arg(writeResult),
                             QMessageBox::Yes, QMessageBox::No);
    }
}

void MyServerSocket::slotNewConnect()
{
    // 第三步 获取客户端链接
    m_pTcpSocket = m_pTcpServer->nextPendingConnection();

    // 连接QTcpSocket的信号槽,以读取新数据
    // 第五步:&QTcpSocket::readyRead表示服务器接收客户端数据后,自动触发readyRead信号
    connect(m_pTcpSocket, &QTcpSocket::readyRead, this, &MyServerSocket::slotReadData);

    // 第六步:&QTcpSocket::disconnected表示服务器接收到客户端断开连接后,自动触发disconnected信号
    connect(m_pTcpSocket, &QTcpSocket::disconnected, this, &MyServerSocket::slotDisConnect);
}

void MyServerSocket::slotReadData()
{
    QByteArray buffer;
    buffer = m_pTcpSocket->readAll();
    ui->textEdit_Receive->setText(buffer);
}

void MyServerSocket::slotDisConnect()
{
	// 关闭连接的操作
}

客户端(Client)

#include "myclientsocket.h"
#include "ui_myclientsocket.h"

#include <QHostAddress>
#include <QDebug>
#include <QMessageBox>

MyClientSocket::MyClientSocket(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyClientSocket)
{
    ui->setupUi(this);

    // 第一步:创建socket对象
    m_pTcpSocket = new QTcpSocket();

    // 第四步:当socket接收缓冲区有新数据到来时,会发出readyRead信号。因此为该信号添加槽函数以读取数据
    connect(m_pTcpSocket, &QTcpSocket::readyRead, this, &MyClientSocket::slotReadData);

    // 设置默认的IP及端口号
    ui->lineEdit_IP->setText("192.168.0.2");
    ui->lineEdit_Port->setText("8888");

    // 第五步:断开与服务器的连接
    connect(m_pTcpSocket, &QTcpSocket::disconnected, this, &MyClientSocket::slotDisConnect);
}

MyClientSocket::~MyClientSocket()
{
    delete this->m_pTcpSocket;// 删除客户端对象
    delete ui;
}

// 连接槽函数
void MyClientSocket::slotConnect()
{
    // 第二步:使用m_pTcpSocket对象连接服务器
    m_pTcpSocket->abort(); // 取消已有连接
    m_pTcpSocket->connectToHost(ui->lineEdit_IP->text(), ui->lineEdit_Port->text().toInt());

    if (!m_pTcpSocket->waitForConnected(30000))
    {
        qDebug() << tr("连接服务器失败,请重新操作!");
    }
    else
    {
        qDebug() << tr("连接服务器成功!");
        QMessageBox::warning(this, tr("连接提示"), tr("连接服务器成功!"),
                             QMessageBox::Yes, QMessageBox::No);
    }
}

// 发送按钮槽函数
void MyClientSocket::slotSend()
{
    // 第三步:使用write向服务器发送数据
    qint16 writeResult = m_pTcpSocket->write(ui->textEdit_Send->toPlainText().toLatin1());

    // 校验数据发送是否成功
    bool bFlush = m_pTcpSocket->flush();
    if (writeResult != -1 && bFlush == 1)
    {
        // 返回值不为-1, 则发送数据成功
        if (0 == writeResult)
            QMessageBox::warning(this, "waring", tr("写数据结果返回值为0"), QMessageBox::Yes, QMessageBox::No);
        QMessageBox::warning(this, "waring", tr("写数据成功!%1").arg(writeResult),
                             QMessageBox::Yes, QMessageBox::No);
    }
}

// 读缓冲区数据
void MyClientSocket::slotReadData()
{
    // 第四步
    QByteArray buffer;
    buffer = m_pTcpSocket->readAll();// 读取缓冲区数据
    ui->textEdit_Receive->setText(buffer); // 设置缓冲区数据
}

void MyClientSocket::slotDisConnect()
{

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kevin_org

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值