How do I know which QNetworkReply belong to the QN

2019-04-07 23:06发布

I can easily get async design in C#

HttpResponseMessage response = await httpClient.GetAsync(InputAddress.Text);
{
    ....// run when request finished. And response closely relation to request.
}

But how can I do that in QT? I find some codes below. But still some questions.

  1. Why does (sentReply == reply) can determine whether it is identical or not? Maybe I can send the same request twice,request A,requst B. Corresponding response is A',B'. but the responses arrive followed order B',A'. The code work or not?
  2. If I want run some code when request finished(like c# code above), How can I do that? I think I can bind a UUID to each request or bind a call back function pointer to request? what is the best way to do that?

    QNetworkAccessManager *manager=new QNetworkAccessManager(this);
    connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(requestFinished(QNetworkReply*)));
    QNetworkRequest request(QUrl(serverUrl));
    QNetworkReply *sentReply = manager->post(request, buffer.toUtf8());
    
    void requestFinished(QNetworkReply *reply)
    {
        QByteArray msg = reply->readAll();
        if (sentReply == reply)
        qDebug("this is it");
    }
    

标签: qt qt5
4条回答
唯我独甜
2楼-- · 2019-04-07 23:16

You can get QNetworkRequest pointer from QNetworkReply

connect(&manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(finishedS(QNetworkReply*)));
//save pointer to orginal request-A in some global(class) variable

void this::finishedS(QNetworkReply* QNR) {
QNetworkRequest *req = QNR->request();
if (req == requestA ) { //request-A stored in global(class) variable
qDebug()<<"It's reply for request-A"
} else {
qDebug()<<"It's reply for request-B"
}
}
查看更多
趁早两清
3楼-- · 2019-04-07 23:22

A graceful way of doing this is connecting to a lambda:

QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkRequest request(QUrl(serverUrl));
QNetworkReply* reply = manager->get(request);

// Note: reply is kept alive by Qt -> capture pointer. request will go
// out of scope -> capture by value (i.e. take a copy)
connect(reply, &QNetworkReply::finished, [request, reply](){
    ....// run when request finished. And response closely relation to request.
    qDebug() << "reply, request: " << reply << request.url(); });

Just pay attention to the scoping rules for captured (between []) variables.

查看更多
smile是对你的礼貌
4楼-- · 2019-04-07 23:22

In my case I created an array of QNetworkAccessManager and QNetworkReply, I had parallel upload progress bars and I needed to send the progress of each to the respective progress bar.

So, I'm sending the signal of reply[i] to the slot(bar()) and in the slot I used a QNetworkReply object that points to the sender

void MyClass::foo()
{
    QNetworkAccessManager *manager[uploadLimit];
    QNetworkReply *reply[uploadLimit];
    reply[i] = manager[i]->post(request, multiPart); //QNetworkRequest request, QHttpMultiPart multiPart
    connect(reply[i], SIGNAL(uploadProgress(qint64,qint64)), this,SLOT(bar(qint64,qint64)));
}

void MyClass::bar(qint64,qint64)
{
    QNetworkReply *rep  = (QNetworkReply*) sender();
}

I removed unnecessary lines, this isn't a working code, I think it gets the point.

查看更多
Ridiculous、
5楼-- · 2019-04-07 23:41

I would suggest the following:

Add a custom Property to the QNetworkReply by using dynamic properties. In the finished Slot you can access them and call the corresponding method.

Example:

QNetworkReply *reply =  
networkAccessManager->get(QNetworkRequest(QUrl("http://url.com"));
reply->setProperty("login", QVariant("logindata");

connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));

replyFinished slot:

QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());

if (reply) {
    if (reply->error() == QNetworkReply::NoError) {
        QString myCustomData = reply->property("login").toString();

        if(myCustomData =="logindata")
            //do something

    }

    reply->deleteLater();
}
查看更多
登录 后发表回答