PDA

View Full Version : QUdpSocket with threads



saman_artorious
23rd November 2013, 18:39
I have a class QUdpSocket which reads data packets from the socket and emits them to another object other than MainWindow. I initialize the construction of this QUdpSocket inside MainWindow and connect its signals.

Today I noticed reading packets from the socket makes ui interaction slow. I think this is because the socket object is defined inside MainWindow implementation and is one of the tasks of MainWindow which takes CPU cycle to itself and releases. To remedy this problem, I thought of defining a QThread and run this thread inside MainWindow.
I believe running the QThread inside MainWindow would not slow down the UI anymore, as the Thread executes kinda like the way a child process initiates and departs from its parent. I hope what I thought of so far is correct.

Next, I have one ambiguity about the inner implementation of QThread Socket. I need to initialize the port and connect the signals in the constructor of course. For the main task which is reading buffer when they become available on the socket, should the main code like "if there is a packet then read, otherwise continue" be implemented in the thread run function? is yes, is it called in regularly in a loop? or it will only execute when the readyRead() signal is triggered?

I would thank if someone could explain this to me with a code template.

Cheers,

anda_skoa
23rd November 2013, 21:19
Are you sure that the reading makes it slow, not the processing of the data? I.e. have you tried without processing the read data?

Cheers,
_

saman_artorious
25th November 2013, 08:45
Are you sure that the reading makes it slow, not the processing of the data? I.e. have you tried without processing the read data?

Cheers,
_

I tested the executable without processing the read data. it is fast:


while(sum > 0)
{
QByteArray datagram;

if(udpsocket->pendingDatagramSize() == -1){
// usleep(1000);
continue;
}
datagram.resize(udpsocket->pendingDatagramSize());
//qDebug() << "udp:" << udpsocket->pendingDatagramSize();
udpsocket->readDatagram(datagram.data(), datagram.size(), host, &myPort);

sumPacket.append(datagram);

sum -= datagram.size();

qDebug() << loop;
loop++;
}
if(sum == 0)
emit dataReceivedClientImage(sumPacket);


However, when it processes the data, it falls behind. That's why in socket read, I cannot read whole packets at one (8 packets), it reads for example 3 packets, pauses a bit and continues receiving the rest. This processing of data is inside the glWidget class:



void GlWidget::createTextureFromBitmap(QByteArray btmp)
{
bytes.clear();
bytes.resize(size * 3 * sizeof(unsigned char));

for(int i = 0, j = 0; i < size*3, j < size; i += 3, j++)
{
bytes[i] = pixelColors[btmp[j]].r;
bytes[i+1] = pixelColors[btmp[j]].g;
bytes[i+2] = pixelColors[btmp[j]].b;
}
updateGL();
qDebug() << "updated..";


I need to set rgb values according to the color table and then call updateGL() to render to the screen.
You know, I cannot think of any solution using threads as well, because if even a thread puts the burden of doing the for processing loop on its shoulders, It finally needs to signal glWidget again to call updateGL(), and as far as either of these processings (for loop or updateGL()) slows down the system, a thread might be of no use!

what do you suggest?

saman_artorious
25th November 2013, 14:40
anyone has any idea?

anda_skoa
25th November 2013, 19:23
anyone has any idea?

I was about to look into this, but no.
Do you think people sit around, bored, just waiting for someone with a question who can't be bother to wait for a couple of hours?

Cheers,
_

P.S.: busy looping is bad, main thread or other doesn't matter. Make have a look at a tutorial on signals/slots.

saman_artorious
25th November 2013, 20:18
I was about to look into this, but no.
Do you think people sit around, bored, just waiting for someone with a question who can't be bother to wait for a couple of hours?

Cheers,
_

P.S.: busy looping is bad, main thread or other doesn't matter. Make have a look at a tutorial on signals/slots.

well, it's ok, your wish. Though this is a misunderstanding. The post left behind in the list, I added a post to put it at the top of the list.
Cheers,

saman_artorious
26th November 2013, 22:05
P.S.: busy looping is bad, main thread or other doesn't matter. Make have a look at a tutorial on signals/slots.

as I think, the problem does not come from the processing and rendering to the screen. Although it is costly and its effects on the loop is visible (cannot read packet from socket at once and quickly, reads a few, pauses, then continues with the remaining), is there a way to tell the loop to try reading from the socket at some other time so that the main thread wouldn't get stuck in the loop continue / sleep instruction?

ChrisW67
27th November 2013, 06:09
The UI can only function smoothly when it reaches the event loop often. By waiting in a loop for some unspecified number of UDP packets/bytes to arrive you have tied your UI thread to the speed and regularity of network reception. You should buffer all the available UDP packets in a slot attached to readyRead(), if there is sufficient data in the buffer process and remove the data (leaving any excess), and return to the event loop (exit the slot) immediately.

Your design implies that a single processable chunk of data is more than one UDP packet, perhaps because it is bigger than the largest possible UDP datagram. If that is not the case you have overcomplicated things.

BTW: Your current design will only process the data if sum goes to zero exactly but you can exit the loop with a negative sum.