PDA

View Full Version : Datastream not reading from socket as expected



scoutycat
9th June 2016, 20:44
I am trying to read values from a socket. when stepping through, everything works as expected until the line "in>>data;". After this line, data is a null pointer. The basic logic is set the socket, wait for enough bytes to read the size of the packet, get the packet size, then read the rest of the data once it's been sent. Socket is a QTcpSocket * and mServer is a QTcpServer *. Checkbytes is just for debug, and it returns the expected value. I have no idea why the datastream isn't populating data??




socket = mServer->nextPendingConnection();

while (socket->bytesAvailable() < (int)sizeof(quint16))
{
if (!socket->waitForReadyRead(Timeout))
{
emit error(socket->error(), socket->errorString());
return;
}
};

quint16 blockSize;

QDataStream in(socket);
in.setVersion(QDataStream::Qt_5_6);
in.setByteOrder(QDataStream::LittleEndian);

char buf[(int)sizeof(quint16)];
socket->peek(buf, sizeof(buf));
blockSize = (*(buf +1) <<8) | *(buf);

while (socket->bytesAvailable() < blockSize )
{
if (!socket->waitForReadyRead(Timeout))
{
emit error(socket->error(), socket->errorString());
return;
}
};

int checkbytes = socket->bytesAvailable(); //this is the expected number

char* data;
in >> data;

//datastream >> allocates using new - caller must destroy
delete[] data;

jefftee
10th June 2016, 02:08
You never allocate any memory to the data pointer, its value is indeterminate. You need to allocate memory to initialize the pointer.

Lesiok
10th June 2016, 07:00
You never allocate any memory to the data pointer, its value is indeterminate. You need to allocate memory to initialize the pointer.
No, from QDataStream doc : Space for the string is allocated using new -- the caller must destroy it with delete[].

jefftee
10th June 2016, 07:07
Oops, sorry for the incorrect advice! Never used QDataStream myself and didn't read the doc before replying!

ChrisW67
11th June 2016, 07:41
QDataStream::operator>>(char *&) is expecting a 32 bit unsigned number of characters followed by that number of characters including the terminating nul byte. Here is a faked incoming packet and read:


#include <QCoreApplication>
#include <QByteArray>
#include <QBuffer>
#include <QDataStream>
#include <QDebug>

int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);

// Fake data packet
QByteArray packet;
QDataStream out(&packet, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_5);
out.setByteOrder(QDataStream::LittleEndian);
out << "Payload";
qDebug() << "Bytes available" << packet.size() << packet.toHex();

// Fake socket
QBuffer *socket = new QBuffer(&packet, qApp);
socket->open(QIODevice::ReadOnly);

// your code
QDataStream in(socket);
in.setVersion(QDataStream::Qt_5_5);
in.setByteOrder(QDataStream::LittleEndian);

// need 4 bytes before this can work ---v

// look ahead for 32-bit string length, the overall block size is 4 bytes longer than the string
char buf[(int)sizeof(quint32)];
socket->peek(buf, sizeof(buf));
int blockSize = (*(buf+3) <<24) | (*(buf+2) <<16) | (*(buf+1) <<8) | *(buf);
blockSize += 4;
qDebug() << "Block size" << blockSize;

// we need to accumulate blockSize bytes before the following can work

char *data = 0;
in >> data;
qDebug() << (void *)data;
if (data)
qDebug() << "String:" << data;
delete[] data;

return 0;
}