【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;
}

 

你可能感兴趣的:(QT)