简体   繁体   中英

Unable to read correctly from socket

I have a server application which sends some xor encrypted strings . I am reading them from my QT client application. Sometimes, the server is slower and I am not able to receive the entire string. I have tried something like below but it gets stuck ( see the comment below). How can I wait until I have the entire data. I tried bytesAviable() but then again i get stuck (infinite loop)

QTcpSocket * sock = static_cast<QTcpSocket*>(this->sender());
if (key == 0)
{
    QString recv(sock->readLine());
    key = recv.toInt();
    qDebug() << "Cheia este " << key;

    char * response = enc_dec("#AUTH|admin|admin",strlen("#AUTH|admin|admin"),key);
    sock->write(response);
}
else
{
    busy = true;
    while (sock->bytesAvailable() > 0)
    {
        unsigned short word;
        sock->read((char*)(&word),2);
        qDebug()<<word;
        //Sleep(100); if i do this than it works great!
        QByteArray bts = sock->read(word);
        while (bts.length() < word)
        {
            char bit; //here get's stuck
            if (sock->read(&bit,1) > 0)
                bts.append(bit);
            sock->flush();
        }

        char * decodat = enc_dec((char*)bts.data(),bts.length() - 2,key);
        qDebug() << decodat;
    }

}

I don't know what the meaning of key == 0 is, but you are almost certainly misusing available() , like almost everybody else who has ever called it, including me. It tells you how much data can be read without blocking . It has nothing to do with how much data may eventually be delivered down the connection, and the reason is that there are TCP APIs that can tell you the former, but not the latter. Indeed the latter doesn't have any real meaning, considering that the peer could keep writing from now until Doomsday. You should just block and loop until you have read the amount of data you need for the next piece of work.

I offer you to do the following:

QObject::connect(this->m_TCPSocket, SIGNAL(readyRead()), this, SLOT(processRecivedDatagrams()));

Some explanation:

  1. It is convinient to create a class instance of which will manage network;
  2. One has the member which is pointer on TCPSocket;
  3. In constructor implement connection of signal from socket readyRead() which is emmited when needed data was delivered with SLOT(processRecivedDatagrams()) . which is responsible for processing recived datagrams/ in this case it is processRecivedDatagrams(), also implement this slot

Mind that class which manages network has to inherit from QObject and also in it s declaration include macros Q_OBject` for MOC.

update:

i also offer you to store recived data in container like stack or queue this will allow you to synhronize sender and reciver ( container in this case acts like buffer )

// SLOT:


void Network::processRecivedDatagrams(void)
{
    if (!this->m_flagLocked) // use analog of mutex 
    {
        this->m_flagLocked = true; // lock resource

    QByteArray datagram;
    do 
    {
        datagram.resize(m_TCPSocket->pendingDatagramSize());
        m_TCPSocket->readDatagram(datagram.data(), datagram.size());
    }
            Qt::String YourString; // actualy I don`t remember how to declare Qt string
    while (m_TCPSocket->hasPendingDatagrams());
    QDataStream in (&datagram, QIODevice::ReadOnly);

        in  >> YourString



        --numberOfDatagrams;
    }

    this->m_flagLocked = false; // unlock resource
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM