Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Server is losing bytes

Server is losing bytes

Scheduled Pinned Locked Moved Unsolved General and Desktop
3 Posts 2 Posters 1.0k 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.
  • canellasC Offline
    canellasC Offline
    canellas
    wrote on last edited by
    #1

    Hi!

    The following code sends a header and a file to a server:

      bool add_audio(const std::string & p_root_files
                       , const std::string & p_server
                       , uint16_t p_port
                       , mother_data_ptr p_mother
                       , babies_data::iterator p_baby
                       , audios_data::iterator p_audio) {
            QTcpSocket _sender;
            _sender.connectToHost(QString(p_server.c_str())
                                  ,p_port);
            if (!_sender.waitForConnected()) {
                return false;
            }
            // header
            {
    
                QByteArray _data;
                QDataStream _block(&_data, QIODevice::WriteOnly);
    
                // mother id
                _block << static_cast<quint32>(p_mother->get_id());
    
                // passwd
                QString _passwd(p_mother->get_passwd().c_str());
                _block << _passwd;
    
                // cmd id
                _block << static_cast<quint16>(commands::add_audio);
    
                // _sender.write(_data);
    
                // baby id
                _block << static_cast<quint16>(p_baby->get_id());
    
                // desc
                QString _desc(p_audio->get_description().c_str());
                qDebug() << "desc = " << _desc << ", "
                         << "desc size = " << _desc.size();
    
                //_block << static_cast<QString::size_type>(_desc.size());
                _block << _desc;
    
                // audio id
                _block << static_cast<quint32>(p_audio->get_id());
    
                // extension
                QString _extension(p_audio->get_extension().c_str());
                _block << _extension;
    
                _sender.write(_data);
                qDebug() << "header with " << _data.size();
                _sender.waitForBytesWritten();
            }
    
            // audio
            {
                quint64 _amount_sent = 0;
                QString _file_name(file_string().
                                   define_audio_full_file_path(p_root_files
                                                               ,p_mother
                                                               ,p_baby
                                                               ,p_audio));
    
                qDebug() << "file name = " << _file_name;
    
                QFile _file(_file_name);
                _file.open(QFile::ReadOnly);
    
                const qint64 _amount = 10 * 1024;
    
                //qint16 _counter = 0;
    
                while (true) {
                    QByteArray _data = _file.read(_amount);
                    if (_data.size() == 0) { break;}
    
                    //qDebug() << ++_counter << ": data size = " << _data.size();
                    _sender.write(_data);
                    _amount_sent += _data.size();
                    _sender.waitForBytesWritten();
                }
                _file.close();
                qDebug() << _amount_sent << " bytes sent";
            }
    
            //_sender.close();
            _sender.disconnectFromHost();
            qDebug() << "##### audio sent ####";
            return true;
        }
    

    The 'ConnectionHandler::read_data' is the slot for the 'readyRead' signal:

    void ConnectionHandler::read_data() {
    
        if (m_connection->bytesAvailable()) {
            QByteArray _data = m_connection->readAll();
    
            qDebug() << "incoming size = " << _data.size();
    
            if (m_first_read) {
                qDebug() << "data = " << _data ;
    
                QDataStream _in(&_data, QIODevice::ReadOnly);
    
                // mother
                quint32 _mother;
                _in >> _mother;
    
                // passwd
                QString _passwd;
                _in >> _passwd;
                qDebug() << "passwd = " << _passwd ;
    
                quint16 _cmd;
                _in >> _cmd;
                qDebug() << "cmd = " << _cmd;
    
                switch (_cmd) {
                case 1:
                    m_cmd_handler = new FileReader(this
                                                   , _mother
                                                   , _in);
                    QByteArray _tmp;
                    _in >> _tmp;
                    qDebug() << "tmp size = " << _tmp.size();
                    (*m_cmd_handler)(_tmp);
                    m_first_read = false;
                    break;
                }
            }
            else {
                if (m_cmd_handler) {
                    (*m_cmd_handler)(_data);
                }
            }
        }
    }
    

    The 'FileReader' constructor is:

    FileReader::FileReader (QObject * p_parent
                            , quint32 p_mother
                            , QDataStream & p_stream )
        : CmdHandler(p_parent)
        , m_mother(p_mother)
        , m_baby()
        , m_desc()
        , m_audio()
        , m_extension()
        , m_file()
        , m_amount_received(0){
    
        // baby id
        p_stream >> m_baby;
        qDebug() << "baby = " << m_baby;
    
        // description
        p_stream >> m_desc;
        qDebug() << "m_desc = " << m_desc << ", "
                 << "m_desc.size() = " << m_desc.size();
    
        // audio id
        p_stream >> m_audio;
        qDebug() << "audio = " << m_audio;// << ", pos = " << p_index;
    
        p_stream >> m_extension;
        qDebug() << "extension = " << m_extension;// << ", pos = " << p_index;
    
        QString _file_name(QString("/var/tmp/") +
                           QString::number(m_mother) +
                           "_" +
                           QString::number(m_baby) +
                           "_" +
                           QString::number(m_audio) +
                           "." +
                           m_extension);
        qDebug() << "file name = " << _file_name;
    
        m_file.setFileName(_file_name);
        if (m_file.exists()) {
            m_file.remove();
        }
    }
    

    And the 'FileReader::operator()(const QByteArray &)' is:

    bool FileReader::operator()(const QByteArray & p_data) {
    
        QByteArray::size_type _data_size = p_data.size();
    
        quint64 _amount_to_write = static_cast<quint64>(_data_size);
    
        if (_amount_to_write > 0) {
    
            const char * _data = p_data.data();
    
            m_file.open(QIODevice::Append);
            quint64 _amount_written = m_file.write(_data, _amount_to_write);
            m_file.close();
    
            m_amount_received += _amount_to_write;
            qDebug() << "amount received = " << m_amount_received
                     << ", to write = " << _amount_to_write << ", "
                     << "writen = " << _amount_written;
    
            return (_amount_written == _amount_to_write);
        }
        return false;
    }
    

    When the transmission finishes, the file at the server side is always smaller than the one at the client side.

    I really can not figure out what I am doing wrong.

    Would please someone point it out?

    Thanks a lot!!!

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2

      readyRead is emitted not only when all the data is available to be read but also when you have chunks (partials) of data available.
      in read_data when you call m_connection->readAll(); you are assuming all the data is already received but that's not always the case.

      Handling this depends on the version of Qt, in Qt5 it's easier using QDataStream transactions, in Qt4 you have to do it manually via checking bytesAvailable().

      Take a look at the readFortune()method of the fortune client example
      Qt4: http://doc.qt.io/qt-4.8/qt-network-fortuneclient-example.html
      Qt5: http://doc.qt.io/qt-5/qtnetwork-fortuneclient-example.html

      P.S.
      sending a password in plain text over an unencrypted socket is NEVER a good idea

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      1 Reply Last reply
      1
      • canellasC Offline
        canellasC Offline
        canellas
        wrote on last edited by
        #3

        Thanks for your time!

        I'll take a closer look to the 'fortune*' examples.

        The password is being sent plain text here, but it will be ciphered in the final code.

        Thanks!

        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 Extensions
        • Unsolved