Results 1 to 1 of 1

Thread: QNAM looses ability to connect/complete GET requests after sleepmode/NIC fail

  1. #1
    Join Date
    Jan 2010
    Posts
    9
    Thanked 1 Time in 1 Post
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default QNAM looses ability to connect/complete GET requests after sleepmode/NIC fail

    Quick problem statement :
    I use GET requests at 30 sec intervals to synchronize the state of an application with a server. A new request is not sent until the previous one completes wether it completes without error or is aborted.

    Due to the lack of timeouts in QNetworkAccessManager i've implemented my own timeout mechanism which calls QNetworkReply::abort() after X(usually around 60) seconds without any activity in the downloadprogress slot.

    Occasionally, most often after the computer has been in sleep mode for some time or in if the NIC looses its connection for a few seconds, the GET request never completes and my custom timeout fires and aborts the request when it clearly should be able to complete. I know it should be able to complete because i am running two instances of the same application in parallell and usually when this happens only one of them looses the ability to complete the GET request. Occasionally both loose the ability but more of then not its only the one.

    Reproducing it
    This is somewhat reproducable by running the attached sampleApp application on a windows host and once it is running putting the computer to sleep. Wake it up after like 5-10 min and in about 1/10(20?) times the QNetworkAccessManager will loose its ability to connect. The timeOutTest is a minimal sample application that reflects the basic functionality of my application and is able to reproduce the problem.

    The frustrating part about trying to debug this is that it hard to reproduce reliably. I have submitted a bug report to nokia but i expect that it will take some time if it even is a bug and i am hoping someone here has experienced something similar and perhaps even has a workaround.


    "main.cpp"
    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include "network.h"
    3. #include <QDebug>
    4.  
    5. int main(int argc, char *argv[])
    6. {
    7. QCoreApplication a(argc, argv);
    8. if(argc < 2/*4*/){
    9. qDebug() << "Usage: ./timeOutTest <server> ";//<username> <password>";
    10. return 0;
    11. }
    12. network *n = new network(argv[1]/*,argv[2],argv[3]*/);
    13. n->startTesting();
    14. return a.exec();
    15. }
    To copy to clipboard, switch view to plain text mode 


    "network.cpp"
    Qt Code:
    1. #include "network.h"
    2. #include <QDebug>
    3. #define NETWORK_TIMEOUT_MS 15000
    4. #define NETWORK_GET_INTERVAL 2000
    5.  
    6. network::network(QString server,/* QString username,QString password,*/QObject *parent) :
    7. QObject(parent)
    8. {
    9. _host = server;
    10. // _username = username;
    11. // _password = password;
    12.  
    13. nam = new QNetworkAccessManager(this);
    14. connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(namfinished(QNetworkReply*)));
    15. connect(nam,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),this,SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
    16. connect(nam,SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),this,SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
    17.  
    18. aborter = new QTimer(this);
    19. connect(aborter,SIGNAL(timeout()),this,SLOT(timeout()));
    20. }
    21.  
    22.  
    23. void network::startTesting()
    24. {
    25. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << "Test is running....";
    26. QTimer::singleShot(NETWORK_GET_INTERVAL,this,SLOT(doCheck()));
    27. }
    28.  
    29. QNetworkRequest network::_initReq()
    30. {
    31. down = 0;
    32. QNetworkRequest req(_host);
    33. // QString uagent = "User-Agent";
    34. // QString uvalue = "timeOutTestSampleApp";
    35. // req.setRawHeader(uagent.toAscii(), uvalue.toAscii());
    36. // QString concatenated = _username + ":" + _password;
    37. // QByteArray data = concatenated.toLocal8Bit().toBase64();
    38. // QString headerData = "Basic " + data;
    39. // req.setRawHeader("Authorization", headerData.toLocal8Bit());
    40. return req;
    41.  
    42. }
    43. void network::downloadProgress(qint64 received, qint64 total)
    44. {
    45. down = received;
    46. if(aborter->isActive())
    47. aborter->stop();
    48. aborter->start(NETWORK_TIMEOUT_MS);
    49. }
    50.  
    51. void network::doCheck()
    52. {
    53. QNetworkRequest req = _initReq();
    54. currentReply = nam->get(req);
    55. connect(currentReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(reply_error(QNetworkReply::NetworkError)));
    56. connect(currentReply,SIGNAL(finished()),this,SLOT(replyfinished()));
    57. connect(currentReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64)));
    58. aborter->start(NETWORK_TIMEOUT_MS);
    59. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << currentReply << " Sending GET request ";
    60. if(!currentReply->isRunning())
    61. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << currentReply << " Is NOT running!!";
    62. }
    63.  
    64. void network::replyfinished()
    65. {
    66. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << this->sender() << " Finished called ";
    67. }
    68.  
    69. void network::timeout()
    70. {
    71. if(currentReply)
    72. {
    73. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << currentReply << " Aborting GET request";
    74. currentReply->abort();
    75. }
    76. else
    77. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << " Fatal error... timeout with invalid qnetworkreply object :S";
    78. }
    79.  
    80. void network::reply_error(QNetworkReply::NetworkError err)
    81. {
    82. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << this->sender() << " Single error " << err;
    83. }
    84.  
    85. void network::authenticationRequired(QNetworkReply *rep, QAuthenticator *auth)
    86. {
    87. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << rep << " AuthenticationRequired called " << auth;
    88. }
    89.  
    90. void network::sslErrors(QNetworkReply *rep, const QList<QSslError> &errors)
    91. {
    92. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << "SslErrors called";
    93. rep->ignoreSslErrors();
    94. }
    95.  
    96. void network::namfinished(QNetworkReply *rep)
    97. {
    98. if(rep->error() == QNetworkReply::NoError)
    99. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << rep << " Finished GET request without error bytesReceived == " << down;
    100. else
    101. qDebug() << QDateTime::currentDateTime().toString("hh:mm:ss:zzz") << rep << " Finished GET request with error " << " ERR( " << rep->errorString() << " ) bytesReceived == ";
    102.  
    103. QTimer::singleShot(NETWORK_GET_INTERVAL,this,SLOT(doCheck()));
    104. rep->deleteLater();
    105. }
    To copy to clipboard, switch view to plain text mode 

    "network.h"
    Qt Code:
    1. #ifndef NETWORK_H
    2. #define NETWORK_H
    3. #include <QObject>
    4. #include <QtNetwork>
    5. #include <QDebug>
    6.  
    7. class network : public QObject
    8. {
    9. Q_OBJECT
    10. public:
    11. explicit network(QString server, /*QString username,QString password,*/QObject *parent = 0);
    12.  
    13. signals:
    14.  
    15. public slots:
    16. void startTesting();
    17.  
    18. //NAM
    19. void namfinished(QNetworkReply *rep);
    20. void sslErrors(QNetworkReply *rep,const QList<QSslError>&errors);
    21. void authenticationRequired(QNetworkReply *rep, QAuthenticator *auth);
    22.  
    23. //REPLY
    24. void downloadProgress(qint64 received, qint64 total);
    25. void reply_error(QNetworkReply::NetworkError err);
    26. void replyfinished();
    27.  
    28. void doCheck();
    29. void timeout();
    30.  
    31. private:
    32. QNetworkRequest _initReq();
    33. QNetworkReply *currentReply;
    34.  
    35. QTimer *aborter;
    36. QTime *timer;
    37. QNetworkAccessManager *nam;
    38.  
    39. qint64 down;
    40.  
    41. QString _host;
    42. QString _username;
    43. QString _password;
    44. };
    45.  
    46. #endif // NETWORK_H
    To copy to clipboard, switch view to plain text mode 
    Attached Files Attached Files

Similar Threads

  1. Dynamic form layout - Ability to add new rows
    By FaradayCage in forum Newbie
    Replies: 1
    Last Post: 22nd July 2010, 16:23
  2. Replies: 2
    Last Post: 5th December 2008, 20:11
  3. MDI child looses focus when app is restored
    By John_P in forum Qt Programming
    Replies: 2
    Last Post: 2nd October 2007, 10:34
  4. Detect when a widget looses focus?
    By thomaspu in forum Qt Programming
    Replies: 9
    Last Post: 16th August 2007, 21:37

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.