Results 1 to 4 of 4

Thread: Problem with IMAP and QTcpSocket

  1. #1
    Join Date
    Aug 2015
    Location
    Poland/UK
    Posts
    30
    Thanks
    6
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Problem with IMAP and QTcpSocket

    Hello, I am writing an Imap client but I need Your help to improve my code, I have tried to solve it, but I don't know how. I guess it is some problem with too big data stored in QByteArray

    As first my program generates very hight CPU usage when I try download using Imap, it is 100% of my Core i7. I am sure it is some bug in download function because as normal does not exceed 10%
    Second problem I found is that download speed slows down about 10kb/s and finish on few bytes/s making my client unusable, (can't download bigger file than 3mb)


    Imap.cpp (download function)
    Qt Code:
    1. void Imap::downloadFile(int message_id, QString filename){
    2. m_logger->Debug("IMAP - downloading: " + this->m_login);
    3. this->login();
    4. sendCommand("a03 EXAMINE INBOX", "a03");
    5. m_dowloadFile = true;
    6. qint64 size = 0;
    7. for(int i = 0; i < m_mailData.count(); i++){
    8. if(m_mailData[i].messageId == message_id){
    9. size = m_mailData[i].size;
    10. }
    11. }
    12. this->getProgressListener()->startTimer();
    13. this->getProgressListener()->setTotal(size);
    14. m_file = new QFile(filename);
    15. if(m_file->open(QIODevice::WriteOnly)) {
    16. sendCommand("a09" + QString::number(message_id) + " fetch " + QString::number(message_id) + " BODY.PEEK[2]", "a09" + QString::number(message_id));
    17. m_file->close();
    18. } else {
    19. m_statusCode = Mailbox::FileWriteError;
    20. }
    21. this->disconectFromHost();
    22. delete m_file;
    23. m_file = NULL;
    24. m_dowloadFile = false;
    25. }
    To copy to clipboard, switch view to plain text mode 

    Part of SocketsBase.cpp
    Qt Code:
    1. ocketsBase::SocketsBase(QString server, int port, bool ssl_mode, EConnectionType type, QObject *parent) :
    2. QObject(parent)
    3. {
    4. m_server = server;
    5. m_port = port;
    6. m_SSLMode = ssl_mode;
    7. m_logger = Logger::getInstance();
    8. m_connectionType = type;
    9. m_file = NULL;
    10. m_dowloadFile = false;
    11. m_finished = false;
    12. m_running = false;
    13. m_timer = new QTimer;
    14. m_Sockets = (m_SSLMode) ? new QSslSocket(this) : new QTcpSocket(this);
    15. connect(m_Sockets, &QAbstractSocket::readChannelFinished, [=]()
    16. {
    17. emit finished();
    18. });
    19.  
    20. connect(m_Sockets, SIGNAL(readyRead()), this, SLOT(ready_read()), Qt::DirectConnection);
    21. connect(m_Sockets, SIGNAL(connected()), this, SLOT(connected()));
    22. connect(m_Sockets, SIGNAL(error(QAbstractSocket::SocketError)), this,SLOT(errorReceived(QAbstractSocket::SocketError)));
    23. connect(m_Sockets, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(stateChanged(QAbstractSocket::SocketState)));
    24. m_success = true;
    25. }
    26.  
    27. void SocketsBase::ready_read()
    28. {
    29. m_finished = false;
    30. connect(m_timer, &QTimer::timeout, [=]() {
    31. emit timeOutReached();
    32. });
    33. m_timer->start(240000);
    34.  
    35.  
    36. if(m_dowloadFile)
    37. {
    38. ProgressListener::getInstance(m_login)->updateProgress(ProgressListener::getInstance(m_login)->getCurrent() + m_Sockets->bytesAvailable());
    39. m_logger->Debug(trUtf8("Bytes available %s"), qPrintable(QString::number(m_Sockets->bytesAvailable())));
    40. }
    41.  
    42. while(!m_Sockets->atEnd()){
    43. if(m_Sockets->bytesAvailable() > 4096){
    44. m_dataBuffer.append(m_Sockets->read(4096));
    45. }else{
    46. m_dataBuffer.append(m_Sockets->readAll());
    47. }
    48. }
    49. m_Sockets->flush();
    50. m_logger->Error(QString::number(m_dataBuffer.size()));
    51.  
    52.  
    53. QRegExp re1(m_currentCode);
    54. QRegExp re(".[\r][?\n]?a[0-9]+ OK Success.*");
    55. QRegExp re2(".[\r]?[\n]?a[0-9]+ OK [fetchFETCH]+.*");
    56.  
    57. if(((re1.indexIn(m_dataBuffer) != -1 && !m_dowloadFile) || (m_dowloadFile && re.indexIn(m_dataBuffer) != -1) )|| re2.indexIn(m_dataBuffer) != -1 || m_currentCode == "-1" || m_connectionType == POP3)
    58. {
    59. if(m_dowloadFile)
    60. {
    61. if(m_file)
    62. {
    63. if(!m_file->isOpen())
    64. if(!m_file->open(QIODevice::WriteOnly))
    65. {
    66. m_logger->Error(trUtf8("Couldn't open file %s to write"), qPrintable(m_file->fileName()));
    67. }
    68.  
    69. QTextStream out(m_file);
    70. out << m_dataBuffer;
    71. //...
    72. }
    73. }
    74. m_timer->stop();
    75. emit finished();
    76. }
    77. //
    78. //...
    79. //...
    80. //
    81. else if(m_dataBuffer.contains("NULL") || m_dataBuffer.contains("null")){
    82. m_logger->Error("Buffer is null !");
    83. m_dataBuffer.clear();
    84. emit finished();
    85. }
    86. }
    To copy to clipboard, switch view to plain text mode 
    m_dataBuffer is QByteArray

    Any suggestions ?

  2. #2
    Join Date
    Aug 2015
    Location
    Poland/UK
    Posts
    30
    Thanks
    6
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Problem with IMAP and QTcpSocket

    This is very important for me, please give me some suggestions. Do You need more code ? Better description or additional informations ?

    Cheers

  3. #3
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Problem with IMAP and QTcpSocket

    Some observations:

    1) you send the fetch command and immediately after close the file
    2) you then disconnect and delete the file

    so how does that even get any data?
    Smells like nested event loop but cold even be as worse as busy-looping

    3) in your ready_read slot you locally create the regular expressions every time?
    4) you parse the buffer every time?
    5) if m_dataBuffer is a QByteArray, why write it with a QTextStream?

    6) you use a lambda to emit finished() when the socket emits readChannelFinished, that cane done way simpler with a signal/signal connection

    Cheers,
    _

  4. The following user says thank you to anda_skoa for this useful post:

    #Dragon (1st August 2016)

  5. #4
    Join Date
    Aug 2015
    Location
    Poland/UK
    Posts
    30
    Thanks
    6
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Problem with IMAP and QTcpSocket

    Thank You ! It works really good after Your suggestions

Similar Threads

  1. Sample Imap Gmail Handshaking
    By patrik08 in forum Qt-based Software
    Replies: 0
    Last Post: 25th September 2013, 18:27
  2. FREELANCE - Pop3 / Imap Qt C++ application
    By prophet0 in forum Jobs
    Replies: 0
    Last Post: 23rd May 2012, 19:20
  3. problem with QTcpSocket
    By Fallen_ in forum Qt Programming
    Replies: 10
    Last Post: 28th November 2010, 12:03
  4. problem with QTcpSocket
    By SuperSonik in forum Qt Programming
    Replies: 8
    Last Post: 31st January 2007, 17:00
  5. Using QTcpSockt to check an IMAP server
    By guilugi in forum Qt Programming
    Replies: 12
    Last Post: 20th March 2006, 09:51

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.