Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QNetworkAccessManager not emitting readyRead or finished signal
Qt 6.12 LTS is out! See what's new in the release blog

QNetworkAccessManager not emitting readyRead or finished signal

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 4 Posters 941 Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • G Offline
    G Offline
    GaryL
    wrote on last edited by
    #1

    hi, can anyone help to debug on this QNetworkAccessManager wrapper? I use a python flask application to receive on http://localhost:8000/ and return 200, "hello world", but when I call session.get(QUrl{"http://localhost:8000/"}), it sucks on waiting for reply debug message and cannot go for no matter QNetworkReply::readyRead or QNetworkReply::finished signal, which cannot exit the loop.
    759e978e-632a-410a-b3fe-d93533dd502b-image.png
    4477c33b-3e69-470b-9266-56de8f731104-image.png
    .h:

    class session : public QObject {
    		Q_OBJECT
    	public:
    		session(void);
    
    		response get(QUrl url, QUrlQuery query = QUrlQuery(),
    					 std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
    		response post(QUrl url, JSON json = JSON(), std::map<QString, QVariant> headers = std::map<QString, QVariant>(),
    					  uint timeout_sec = 60);
    		response post(QUrl url, QUrlQuery data = QUrlQuery(),
    					  std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
    
    	signals:
    		void request_start_signal(void);
    
    	public slots:
    		void request_process_slot(void);
    
    	private:
    		QNetworkAccessManager manager;
    		QByteArray request_data;
    		MethodsEnum request_method;
    		bool is_finished = true;
    		bool is_running = false;
    		QNetworkRequest* request = nullptr;
    		QNetworkReply* reply = nullptr;
    
    		response wait_for_reply(uint timeout_sec);
    	};
    

    .cpp

    session::session(void) { connect(this, &session::request_start_signal, this, &session::request_process_slot); }
    
    	void session::request_process_slot(void) {
    		qDebug() << "request slot";
    		this->is_running = true;
    		switch (request_method) {
    			case GET: this->reply = this->manager.get(*this->request); break;
    			case POST: this->reply = this->manager.post(*this->request, this->request_data); break;
    			default: break;
    		}
    		QEventLoop loop;
    		connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
    		loop.exec();
    		qDebug() << "request slot finished";
    		this->is_finished = true;
    		this->is_running = false;
    	}
    
    	response session::wait_for_reply(uint timeout_sec) {
    		uint64_t start_time = QDateTime::currentMSecsSinceEpoch();
    		while (!this->is_finished) { // just do blocking request is fine for this project's case
    			qDebug() << "waiting for reply" << (QDateTime::currentMSecsSinceEpoch() - start_time) / 1000;
    			if (timeout_sec > 0 && QDateTime::currentMSecsSinceEpoch() - start_time > timeout_sec * 1000) {
    				qDebug() << "request timeout";
    				this->is_finished = true;
    				this->reply->disconnect();
    				delete this->reply;
    				return response();
    			}
    			QThread::msleep(100);
    		}
    		response res = response(this->request, this->reply);
    		this->reply->disconnect();
    		delete this->request;
    		this->request = nullptr;
    		delete this->reply;
    		this->reply = nullptr;
    		return res;
    	}
    
    	response session::get(QUrl url, QUrlQuery query, std::map<QString, QVariant> headers, uint timeout_sec) {
    		qDebug() << "GET";
    		while (!this->is_finished) {
    			qDebug() << "waiting for prev request to finish";
    			QThread::msleep(100);
    		}
    		url.setQuery(query.query());
    		if (this->request != nullptr) {
    			delete this->request;
    		}
    		this->request = new QNetworkRequest(url);
    		qDebug() << 3;
    		for (const auto& [key, value] : headers) {
    			this->request->setRawHeader(key.toUtf8(), value.toByteArray());
    		}
    		this->request_method = GET;
    		this->is_finished = false;
    		emit this->request_start_signal();
    		return this->wait_for_reply(timeout_sec);
    	}
    
    Christian EhrlicherC J.HilkJ 2 Replies Last reply
    0
    • G GaryL

      hi, can anyone help to debug on this QNetworkAccessManager wrapper? I use a python flask application to receive on http://localhost:8000/ and return 200, "hello world", but when I call session.get(QUrl{"http://localhost:8000/"}), it sucks on waiting for reply debug message and cannot go for no matter QNetworkReply::readyRead or QNetworkReply::finished signal, which cannot exit the loop.
      759e978e-632a-410a-b3fe-d93533dd502b-image.png
      4477c33b-3e69-470b-9266-56de8f731104-image.png
      .h:

      class session : public QObject {
      		Q_OBJECT
      	public:
      		session(void);
      
      		response get(QUrl url, QUrlQuery query = QUrlQuery(),
      					 std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
      		response post(QUrl url, JSON json = JSON(), std::map<QString, QVariant> headers = std::map<QString, QVariant>(),
      					  uint timeout_sec = 60);
      		response post(QUrl url, QUrlQuery data = QUrlQuery(),
      					  std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
      
      	signals:
      		void request_start_signal(void);
      
      	public slots:
      		void request_process_slot(void);
      
      	private:
      		QNetworkAccessManager manager;
      		QByteArray request_data;
      		MethodsEnum request_method;
      		bool is_finished = true;
      		bool is_running = false;
      		QNetworkRequest* request = nullptr;
      		QNetworkReply* reply = nullptr;
      
      		response wait_for_reply(uint timeout_sec);
      	};
      

      .cpp

      session::session(void) { connect(this, &session::request_start_signal, this, &session::request_process_slot); }
      
      	void session::request_process_slot(void) {
      		qDebug() << "request slot";
      		this->is_running = true;
      		switch (request_method) {
      			case GET: this->reply = this->manager.get(*this->request); break;
      			case POST: this->reply = this->manager.post(*this->request, this->request_data); break;
      			default: break;
      		}
      		QEventLoop loop;
      		connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
      		loop.exec();
      		qDebug() << "request slot finished";
      		this->is_finished = true;
      		this->is_running = false;
      	}
      
      	response session::wait_for_reply(uint timeout_sec) {
      		uint64_t start_time = QDateTime::currentMSecsSinceEpoch();
      		while (!this->is_finished) { // just do blocking request is fine for this project's case
      			qDebug() << "waiting for reply" << (QDateTime::currentMSecsSinceEpoch() - start_time) / 1000;
      			if (timeout_sec > 0 && QDateTime::currentMSecsSinceEpoch() - start_time > timeout_sec * 1000) {
      				qDebug() << "request timeout";
      				this->is_finished = true;
      				this->reply->disconnect();
      				delete this->reply;
      				return response();
      			}
      			QThread::msleep(100);
      		}
      		response res = response(this->request, this->reply);
      		this->reply->disconnect();
      		delete this->request;
      		this->request = nullptr;
      		delete this->reply;
      		this->reply = nullptr;
      		return res;
      	}
      
      	response session::get(QUrl url, QUrlQuery query, std::map<QString, QVariant> headers, uint timeout_sec) {
      		qDebug() << "GET";
      		while (!this->is_finished) {
      			qDebug() << "waiting for prev request to finish";
      			QThread::msleep(100);
      		}
      		url.setQuery(query.query());
      		if (this->request != nullptr) {
      			delete this->request;
      		}
      		this->request = new QNetworkRequest(url);
      		qDebug() << 3;
      		for (const auto& [key, value] : headers) {
      			this->request->setRawHeader(key.toUtf8(), value.toByteArray());
      		}
      		this->request_method = GET;
      		this->is_finished = false;
      		emit this->request_start_signal();
      		return this->wait_for_reply(timeout_sec);
      	}
      
      Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @GaryL said in QNetworkAccessManager not emitting readyRead or finished signal:

      QThread::msleep(100);

      WTF?

      Qt is async so post your request, return to the event loop and when the answer arrives Qt will call your slot.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      2
      • G GaryL

        hi, can anyone help to debug on this QNetworkAccessManager wrapper? I use a python flask application to receive on http://localhost:8000/ and return 200, "hello world", but when I call session.get(QUrl{"http://localhost:8000/"}), it sucks on waiting for reply debug message and cannot go for no matter QNetworkReply::readyRead or QNetworkReply::finished signal, which cannot exit the loop.
        759e978e-632a-410a-b3fe-d93533dd502b-image.png
        4477c33b-3e69-470b-9266-56de8f731104-image.png
        .h:

        class session : public QObject {
        		Q_OBJECT
        	public:
        		session(void);
        
        		response get(QUrl url, QUrlQuery query = QUrlQuery(),
        					 std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
        		response post(QUrl url, JSON json = JSON(), std::map<QString, QVariant> headers = std::map<QString, QVariant>(),
        					  uint timeout_sec = 60);
        		response post(QUrl url, QUrlQuery data = QUrlQuery(),
        					  std::map<QString, QVariant> headers = std::map<QString, QVariant>(), uint timeout_sec = 60);
        
        	signals:
        		void request_start_signal(void);
        
        	public slots:
        		void request_process_slot(void);
        
        	private:
        		QNetworkAccessManager manager;
        		QByteArray request_data;
        		MethodsEnum request_method;
        		bool is_finished = true;
        		bool is_running = false;
        		QNetworkRequest* request = nullptr;
        		QNetworkReply* reply = nullptr;
        
        		response wait_for_reply(uint timeout_sec);
        	};
        

        .cpp

        session::session(void) { connect(this, &session::request_start_signal, this, &session::request_process_slot); }
        
        	void session::request_process_slot(void) {
        		qDebug() << "request slot";
        		this->is_running = true;
        		switch (request_method) {
        			case GET: this->reply = this->manager.get(*this->request); break;
        			case POST: this->reply = this->manager.post(*this->request, this->request_data); break;
        			default: break;
        		}
        		QEventLoop loop;
        		connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
        		loop.exec();
        		qDebug() << "request slot finished";
        		this->is_finished = true;
        		this->is_running = false;
        	}
        
        	response session::wait_for_reply(uint timeout_sec) {
        		uint64_t start_time = QDateTime::currentMSecsSinceEpoch();
        		while (!this->is_finished) { // just do blocking request is fine for this project's case
        			qDebug() << "waiting for reply" << (QDateTime::currentMSecsSinceEpoch() - start_time) / 1000;
        			if (timeout_sec > 0 && QDateTime::currentMSecsSinceEpoch() - start_time > timeout_sec * 1000) {
        				qDebug() << "request timeout";
        				this->is_finished = true;
        				this->reply->disconnect();
        				delete this->reply;
        				return response();
        			}
        			QThread::msleep(100);
        		}
        		response res = response(this->request, this->reply);
        		this->reply->disconnect();
        		delete this->request;
        		this->request = nullptr;
        		delete this->reply;
        		this->reply = nullptr;
        		return res;
        	}
        
        	response session::get(QUrl url, QUrlQuery query, std::map<QString, QVariant> headers, uint timeout_sec) {
        		qDebug() << "GET";
        		while (!this->is_finished) {
        			qDebug() << "waiting for prev request to finish";
        			QThread::msleep(100);
        		}
        		url.setQuery(query.query());
        		if (this->request != nullptr) {
        			delete this->request;
        		}
        		this->request = new QNetworkRequest(url);
        		qDebug() << 3;
        		for (const auto& [key, value] : headers) {
        			this->request->setRawHeader(key.toUtf8(), value.toByteArray());
        		}
        		this->request_method = GET;
        		this->is_finished = false;
        		emit this->request_start_signal();
        		return this->wait_for_reply(timeout_sec);
        	}
        
        J.HilkJ Offline
        J.HilkJ Offline
        J.Hilk
        Moderators
        wrote on last edited by
        #3

        @GaryL said in QNetworkAccessManager not emitting readyRead or finished signal:

        QThread::msleep(100)

        no event handling, no signals, no slots being called

        while (!this->is_finished)

        same here


        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


        Q: What's that?
        A: It's blue light.
        Q: What does it do?
        A: It turns blue.

        1 Reply Last reply
        0
        • G Offline
          G Offline
          GaryL
          wrote on last edited by
          #4

          @Christian-Ehrlicher @J-Hilk

          Thanks for your help, but the problem is in function request_process_slot, not in function wait_for_reply.

          I have used a QEventLoop loop to block the process, and connect it with connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);. but then not matter I use QNetworkReply::readyRead or QNetworkReply::finished as signal, it still sucks on this event loop.

          I have connect(this, &session::request_start_signal, this, &session::request_process_slot); in the constructor, so request_process_slot can be called when emit this->request_start_signal(); in get function.

          Christian EhrlicherC 1 Reply Last reply
          0
          • G GaryL

            @Christian-Ehrlicher @J-Hilk

            Thanks for your help, but the problem is in function request_process_slot, not in function wait_for_reply.

            I have used a QEventLoop loop to block the process, and connect it with connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);. but then not matter I use QNetworkReply::readyRead or QNetworkReply::finished as signal, it still sucks on this event loop.

            I have connect(this, &session::request_start_signal, this, &session::request_process_slot); in the constructor, so request_process_slot can be called when emit this->request_start_signal(); in get function.

            Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @GaryL said in QNetworkAccessManager not emitting readyRead or finished signal:

            I have used a QEventLoop loop to block the process

            No!

            Go back to the Qt event loop.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            G 1 Reply Last reply
            1
            • Christian EhrlicherC Christian Ehrlicher

              @GaryL said in QNetworkAccessManager not emitting readyRead or finished signal:

              I have used a QEventLoop loop to block the process

              No!

              Go back to the Qt event loop.

              G Offline
              G Offline
              GaryL
              wrote on last edited by
              #6

              @Christian-Ehrlicher umm... not really understand, you mean sth like this?

              session::session(void) { connect(this, &session::request_start_signal, this, &session::request_process_slot); }
              
              	void session::request_process_slot(void) {
              		qDebug() << "request slot";
              		this->is_running = true;
              		switch (request_method) {
              			case GET: this->reply = this->manager.get(*this->request); break;
              			case POST: this->reply = this->manager.post(*this->request, this->request_data); break;
              			default: break;
              		}
              	}
              
              	response session::wait_for_reply(uint timeout_sec) {
              		while (this->reply == nullptr) {
              			QThread::msleep(10);
              		}
              		QEventLoop loop;
              		connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
              		loop.exec();
              		this->is_finished = true;
              		response res = response(this->request, this->reply);
              		this->reply->disconnect();
              		delete this->request;
              		this->request = nullptr;
              		delete this->reply;
              		this->reply = nullptr;
              		return res;
              	}
              
              	response session::get(QUrl url, QUrlQuery query, std::map<QString, QVariant> headers, uint timeout_sec) {
              		qDebug() << "GET";
              		while (!this->is_finished) {
              			qDebug() << "waiting for prev request to finish";
              			QThread::msleep(100);
              		}
              		url.setQuery(query.query());
              		if (this->request != nullptr) {
              			delete this->request;
              		}
              		this->request = new QNetworkRequest(url);
              		for (const auto& [key, value] : headers) {
              			this->request->setRawHeader(key.toUtf8(), value.toByteArray());
              		}
              		this->request_method = GET;
              		this->is_finished = false;
              		emit this->request_start_signal();
              		return this->wait_for_reply(timeout_sec);
              	}
              
              JonBJ 1 Reply Last reply
              0
              • G GaryL

                @Christian-Ehrlicher umm... not really understand, you mean sth like this?

                session::session(void) { connect(this, &session::request_start_signal, this, &session::request_process_slot); }
                
                	void session::request_process_slot(void) {
                		qDebug() << "request slot";
                		this->is_running = true;
                		switch (request_method) {
                			case GET: this->reply = this->manager.get(*this->request); break;
                			case POST: this->reply = this->manager.post(*this->request, this->request_data); break;
                			default: break;
                		}
                	}
                
                	response session::wait_for_reply(uint timeout_sec) {
                		while (this->reply == nullptr) {
                			QThread::msleep(10);
                		}
                		QEventLoop loop;
                		connect(this->reply, &QNetworkReply::readyRead, &loop, &QEventLoop::quit);
                		loop.exec();
                		this->is_finished = true;
                		response res = response(this->request, this->reply);
                		this->reply->disconnect();
                		delete this->request;
                		this->request = nullptr;
                		delete this->reply;
                		this->reply = nullptr;
                		return res;
                	}
                
                	response session::get(QUrl url, QUrlQuery query, std::map<QString, QVariant> headers, uint timeout_sec) {
                		qDebug() << "GET";
                		while (!this->is_finished) {
                			qDebug() << "waiting for prev request to finish";
                			QThread::msleep(100);
                		}
                		url.setQuery(query.query());
                		if (this->request != nullptr) {
                			delete this->request;
                		}
                		this->request = new QNetworkRequest(url);
                		for (const auto& [key, value] : headers) {
                			this->request->setRawHeader(key.toUtf8(), value.toByteArray());
                		}
                		this->request_method = GET;
                		this->is_finished = false;
                		emit this->request_start_signal();
                		return this->wait_for_reply(timeout_sec);
                	}
                
                JonBJ Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #7

                @GaryL
                As the other two responders have said, you must not use either of

                while (!this->is_finished)
                QThread::msleep(100)
                

                They go against how an event-driven framework like Qt works.

                G 1 Reply Last reply
                0
                • JonBJ JonB

                  @GaryL
                  As the other two responders have said, you must not use either of

                  while (!this->is_finished)
                  QThread::msleep(100)
                  

                  They go against how an event-driven framework like Qt works.

                  G Offline
                  G Offline
                  GaryL
                  wrote on last edited by
                  #8

                  @JonB I am doing is because I original use qDebug() to print the variables of this->reply inside the loop so to find out what is going on, but it turns out that all variables seems normal. On the other hand, the python flask script do have receive a request and returned 200, "Hello world", so I don't know what is actually going on...

                  JonBJ J.HilkJ 2 Replies Last reply
                  0
                  • G GaryL

                    @JonB I am doing is because I original use qDebug() to print the variables of this->reply inside the loop so to find out what is going on, but it turns out that all variables seems normal. On the other hand, the python flask script do have receive a request and returned 200, "Hello world", so I don't know what is actually going on...

                    JonBJ Offline
                    JonBJ Offline
                    JonB
                    wrote on last edited by JonB
                    #9

                    @GaryL
                    At this point I would suggest you dump calling your code, especially wait_for_reply(), for a while. Just produce a minimal program without while, is_finished, msleep, QEventLoop etc. Just connect the reply's readyRead() to something which outputs whatever it receives, do your get() or post() and verify you get the returned result (without "waiting" for it).

                    G 1 Reply Last reply
                    0
                    • G GaryL

                      @JonB I am doing is because I original use qDebug() to print the variables of this->reply inside the loop so to find out what is going on, but it turns out that all variables seems normal. On the other hand, the python flask script do have receive a request and returned 200, "Hello world", so I don't know what is actually going on...

                      J.HilkJ Offline
                      J.HilkJ Offline
                      J.Hilk
                      Moderators
                      wrote on last edited by
                      #10

                      @GaryL said in QNetworkAccessManager not emitting readyRead or finished signal:

                      so I don't know what is actually going on...

                      again, you're blocking any and all event handling in your qt application. The OS doesn't care about that and forwards your requests, thats why you may see stuff on the other side.

                      Btw, the Pythonfyed c++ is hurting my soul :P, deeply


                      Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                      Q: What's that?
                      A: It's blue light.
                      Q: What does it do?
                      A: It turns blue.

                      1 Reply Last reply
                      0
                      • JonBJ JonB

                        @GaryL
                        At this point I would suggest you dump calling your code, especially wait_for_reply(), for a while. Just produce a minimal program without while, is_finished, msleep, QEventLoop etc. Just connect the reply's readyRead() to something which outputs whatever it receives, do your get() or post() and verify you get the returned result (without "waiting" for it).

                        G Offline
                        G Offline
                        GaryL
                        wrote on last edited by
                        #11

                        @JonB @J-Hilk I have actually used another url which is https://accounts.spotify.com/api/token, this url can be successfully exceuted with the above code and get its return json, but the same code fails with http://localhost:8000/ or https://api.spotify.com/v1/me/player/currently-playing

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt
                        • Unsolved