QT实例 - 实现http通信

QT实现通过HTTP与服务器进行交互

原文链接:https://blog.csdn.net/hwc3737/article/details/108367037

添加依赖:

①在项目的.pro文件中添加:

QT += network

②引入相关头文件
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>

实现步骤:

①定义一个QNetworkAccessManager对象和一个QNetworkReply对象,作为主窗口的私有成员对象
QNetworkAccessManager *datauploader;
QNetworkReply *datareply;
与下面会用到的QNetworkRequest网络请求类,他们三者的关系可以简单用下列的图片表示:

在这里插入图片描述

理解:

QNetworkAccessManager类作为一个媒介,通过它调用get和post方法将QNetworkRequest请求对象发送至服务器,并通过QNetworkReply类接收服务器响应的信息。

②在构造函数中实例化QNetworkAccessManager对象
this->datauploader = new QNetworkAccessManager(this);
③http请求发送函数
void Widget::sendMessToServer()
{
	QString severUrl = "http://xxxx";		//注意不是https,否则会无法工作
	QString jsondata = "{\"name\": \"xxx\", \"age\": 32}";
	QUrl url(serverUrl);					//服务请求接口
	//创建一个请求对象,并设置服务接口地址
    QNetworkRequest request(url);
    //设置包含默认的请求头
    request.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json"));
    //此处可进行添加必要的请求头(后端服务器要求的请求头)
    request.setRawHeader("headmess", headmess.toUtf8());	//此处不做变量定义,请自行替换		
    
    //需要json数据格式转化成字节数组
    QByteArray bytearray = jsondata.toUtf8();
    //以上面定义的datareply(QNetworkReply服务响应对象)接收返回
    datareply = datauploader->post(request,bytearray);
    //连接信号与槽,当接收到返回数据时便会触发槽函数dataUploadFinished()
    connect(datareply,SIGNAL(finished()),this,SLOT(dataUploadFinished()));
}
④接收响应信息
void Widget::dataUploadFinished()
{
	//无出现错误
    if(datareply->error() == QNetworkReply::NoError) {
        QString mess = datareply->readAll();
		QMessageBox::information(this, "提示", "接收到返回:" + mess, "确定");

		//重置响应对象
        datareply->deleteLater();
        datareply = NULL;
    }else{//出现错误
        QString mess = datareply->errorString();
        QMessageBox::critical(this, "提示", "请求出错,错误信息为:" + mess, "确定");
        
        datareply->deleteLater();
    }
    //断开信号与槽
    disconnect(datareply,SIGNAL(finished()),this,SLOT(dataUploadFinished()));
}
⑤若需要上传图片,需要做出以下修改:
1)添加引入头文件:
#include <QHttpMultiPart>
#include <QDataStream>
#include <QTextCodec>
#include <QHttpPart>
2)定义图片缓存对象,作为私有成员变量:
QFile *imgFile;
3)工作函数修改:
void Widget::sendMessToServer()
{
	QString severUrl = "http://xxxx";
	QString photoPath = "xxxx";		//photoPath为所需上传图片的路径
	
	//QHttpMultiPart用以创建包含多个消息体的消息头
	QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QHttpPart imagePart;
    //以下为包含的默认消息头
    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"image.jpg\";"));
    //提取图片
    imgFile = new QFile(photoPath);		
    imgFile->open(QIODevice::ReadOnly);
    //将图片作为请求正文并添加进去
    imagePart.setBodyDevice(imgFile);
    imgFile->setParent(multiPart);
    multiPart->append(imagePart);
    //定义请求对象
    QNetworkRequest request(QUrl(serverUrl));
    //此处可进行添加必要的请求头(后端服务器要求的请求头)
    request.setRawHeader("headmess", headmess.toUtf8());	//此处不做变量定义,请自行替换
	
	//同上,以响应对象接收返回
    photoreply = photouploader->post(request, multiPart);
    //此处不可少
    multiPart->setParent(photoreply);
    //连接信号与槽,处理方法同上
    connect(photoreply,SIGNAL(finished()),this,SLOT(photoUploadFinished()));
}

本文为作者从实际项目中脱离出来的总结,仅供参考,亲测可稳定运行。
若有发现问题,欢迎留言补充。
转载请注明出处。

  • 6
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt提供了一些多线程类和网络类,可以很方便地实现TCP通信。下面是一个简单的例子: 1. 创建一个继承自QObject的MyTcp类,用来处理TCP通信的相关操作。 ```cpp class MyTcp : public QObject { Q_OBJECT public: explicit MyTcp(QObject *parent = nullptr); signals: void messageReceived(const QString& message); public slots: void connectToHost(const QString& ip, quint16 port); void sendMessage(const QString& message); void disconnectFromHost(); private: QTcpSocket* m_tcpSocket; }; ``` 2. 实现MyTcp类的构造函数和槽函数。 ```cpp MyTcp::MyTcp(QObject *parent) : QObject(parent) { m_tcpSocket = new QTcpSocket(this); connect(m_tcpSocket, &QTcpSocket::readyRead, this, [this]() { QByteArray bytes = m_tcpSocket->readAll(); QString message = QString::fromUtf8(bytes.constData(), bytes.length()); emit messageReceived(message); }); connect(m_tcpSocket, &QTcpSocket::disconnected, this, []() { qDebug() << "Disconnected from server"; }); } void MyTcp::connectToHost(const QString& ip, quint16 port) { m_tcpSocket->connectToHost(ip, port); } void MyTcp::sendMessage(const QString& message) { m_tcpSocket->write(message.toUtf8()); } void MyTcp::disconnectFromHost() { m_tcpSocket->disconnectFromHost(); } ``` 3. 在GUI线程中创建一个实例对象,并与MyTcp类的信号和槽进行连接。 ```cpp MyTcp* tcp = new MyTcp(); connect(tcp, &MyTcp::messageReceived, this, [this](const QString& message) { ui->textEdit->append(message); }); tcp->connectToHost("127.0.0.1", 1234); tcp->sendMessage("Hello, world!"); ``` 4. 在另一个线程中使用MyTcp类进行TCP通信。 ```cpp void TcpWorker::run() { MyTcp tcp; connect(&tcp, &MyTcp::messageReceived, this, [this](const QString& message) { qDebug() << message; }); tcp.connectToHost("127.0.0.1", 1234); tcp.sendMessage("Hello, world!"); exec(); //等待事件循环结束 } ``` 以上就是一个简单的Qt多线程实现TCP通信的例子。需要注意的是,在GUI线程和工作线程之间进行通信时,应当使用Qt的信号和槽机制,以避免线程安全问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值