【QT学习】QNetworkAccessManager的使用,发送http请求。

背景:需要使用QNetworkAccessManager周期性以及多次发送异步http请求。但是发现程序过了很长时间后就会崩溃,终端报错:

GLib-ERROR **: Creating pipes for GWakeup: Too many open files ...

后来发现原因是每一个周期都会对QNetworkAccessManager进行new操作导致,内存一直没有消失,QNetworkAccessManager进行get时产生的线程应该也没有消失,句柄就会不断的增加。

解决方法:

(1)如果程序中http请求都是同步的话,QNetworkAccessManager使用临时对象即可,函数结束后对象就会销毁,不会出现问题。例如:

QNetworkAccessManager manager;
/*设置http请求*/
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=UTF-8"));

...........

/*get http 数据*/
QNetworkReply*reply =manager.get(req);

/*阻塞loop请求:同步处理*/
QEventLoop eventLoop;
connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
ret = httpReply(reply);

(2)如果程序中http请求是异步的,则不能用临时的栈对象(如(1)),会导致http还没有回复的时候,manager对象因为函数的结束而销毁,进而connect函数永远都不会进来。有如下几种方法:

(2.1)每一次循环或者申请的时候,new一个对象,直接在函数结束的时候delete QNetworkAccessManager对象

QNetworkAccessManager *manager = new QNetworkAccessManager(this);


/*设置http请求*/
QNetworkRequest req;
req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=UTF-8"));

..........


connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(httpReply(QNetworkReply*)));
    
/*将manager delete*/
connect(manager, SIGNAL(finished(QNetworkReply*)), manager, SLOT(deleteLater()));
   
/*get http 数据*/
QNetworkReply*reply =manager->get(req);

(2.2)一个应用程序只需要定义一个QNetworkAccessManager就行,没有必要每次循环都new一个。connect函数不能放在循环中,要在变量初始化后。

构造函数中
manager = new QNetworkAccessManager(this);//manager是成员变量
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(httpRepy(QNetworkReply*)));
for (int index = 0; index < 10; index++)
{
    httpReq(ASYNC);
}


请求函数实现
int httpReq(unsigned char syncType)
{
    int ret = 0;

    /*设置http请求*/
    QNetworkRequest req;
    req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant("application/json;charset=UTF-8"));
    
    ..........

    /*get http 数据*/
    QNetworkReply*reply =mapSyncManagerSta->get(mapSyncReq);

    /*同步*/
    if(SYNC == syncType)
    {
        /*阻塞loop请求:同步处理*/
        QEventLoop eventLoop;
        connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
        eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
    }

    
    return ret;
}

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过Qt的网络模块QNetworkAccessManager和QNetworkRequest来向C服务器发送HTTP请求。 具体步骤如下: 1. 创建QNetworkAccessManager对象,用于发送请求和接收响应。 2. 创建QNetworkRequest对象,设置请求的URL地址和其他相关信息(如请求头信息)。 3. 调用QNetworkAccessManager的get()、post()等函数发送请求,并将请求结果保存在QNetworkReply对象中。 4. 通过QNetworkReply对象获取响应数据,如状态码、HTTP头信息和响应正文等。 以下是一个示例代码: ``` #include <QCoreApplication> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 创建QNetworkAccessManager对象 QNetworkAccessManager manager; // 创建QNetworkRequest对象,设置请求URL和其他信息 QUrl url("http://localhost:80/api"); QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); // 发送GET请求 QNetworkReply *reply = manager.get(request); // 处理响应 QObject::connect(reply, &QNetworkReply::finished, [&]() { if (reply->error() == QNetworkReply::NoError) { qDebug() << "Status code:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << "Response headers:" << reply->rawHeaderPairs(); qDebug() << "Response body:" << reply->readAll(); } else { qDebug() << "Error:" << reply->errorString(); } reply->deleteLater(); a.quit(); }); return a.exec(); } ``` 在上面的示例中,我们向URL为http://localhost:80/api的C服务器发送了一个GET请求,并将请求的Content-Type设置为application/json。在响应中,我们输出了状态码、HTTP头信息和响应正文。最后,我们通过reply->deleteLater()释放了QNetworkReply对象的内存,并通过a.quit()停止Qt事件循环。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值