Sending UDP packets with QUdpSocket returns "UnknownSocketError" randomly
-
I'm trying to read a binary file, slice it into packets and send them with UDP protocol using QUdpSocket. Reading a file and sending packets are performed in two concurrent threads. This is a simplified version of my code.
In ReadWriteManager class I have this slot:
void ReadWriteManager::requestDataFromFile() { static int cursor{}; if (!flagData[cursor]) { inputFile.read(reinterpret_cast<char*>(buffer + cursor * readSize), readSize * sizeof(uint8_t)); flagData[cursor++] = true; if (cursor == nChunks) cursor= 0; } else { qDebug() << "----- ! Frame Loss ! -----"; } if (!stopped) QTimer::singleShot(1, this, SLOT(requestDataFromFile())); }
In UDPSender:
UDPSender::UDPSender(QObject *parent) : QObject(parent) { mSocket = new QUdpSocket(this); mSocket->setPauseMode(QUdpSocket::PauseMode::PauseNever); mSocket->connectToHost(QHostAddress("192.168.1.255"), 2000); }
and I have this slot:
void UDPSender::sendPackets() { int cursor{}; while (!stopped) { if (flagData[cursor]) { for (int i{}; i < readSize / payloadLen; ++i) { memcpy(packet.data() + 4, buffer + cursor * readSize + i * payloadLen, payloadLen * sizeof(uint8_t)); if (mSocket->write(packet.constData(), packet.size()) < packet.size()) qDebug() << mSocket->error() << ", " << mSocket->errorString(); } flagData[cursor++] = false; if (cursor == nChunks) cursor= 0; } } }
flagData and buffer arrays are shared between the two classes, and I'm kinda implementing my own mutex and circular buffer.
nChunks = 512
,payloadLen = 1460
andreadSize = a * payloadLen
wherea
is an integer. I control the transmission rate witha
.When I run the program, I randomly see
QAbstractSocket::UnknownSocketError, "Unknown error"
in the console and it happens rarely (compared to the bit rate) but it's still there and the higher the bit rate, the more often I see this error. Do you have any suggestions on what the causes could be and how I can fix this? Is there any constraint on payloadLen? And what is the maximum bit rate I can achieve with connected socket in QUdpSocket? I'm using Windows 10, Qt 5.14.1. -
@Nastaran said in Sending UDP packets with QUdpSocket returns "UnknownSocketError" randomly:
while (!stopped) {
first of, I would get rid of the endless while loop, see if that is the cause of the error.
-
@Nastaran said in Sending UDP packets with QUdpSocket returns "UnknownSocketError" randomly:
while (!stopped) {
first of, I would get rid of the endless while loop, see if that is the cause of the error.
-
I'm trying to read a binary file, slice it into packets and send them with UDP protocol using QUdpSocket. Reading a file and sending packets are performed in two concurrent threads. This is a simplified version of my code.
In ReadWriteManager class I have this slot:
void ReadWriteManager::requestDataFromFile() { static int cursor{}; if (!flagData[cursor]) { inputFile.read(reinterpret_cast<char*>(buffer + cursor * readSize), readSize * sizeof(uint8_t)); flagData[cursor++] = true; if (cursor == nChunks) cursor= 0; } else { qDebug() << "----- ! Frame Loss ! -----"; } if (!stopped) QTimer::singleShot(1, this, SLOT(requestDataFromFile())); }
In UDPSender:
UDPSender::UDPSender(QObject *parent) : QObject(parent) { mSocket = new QUdpSocket(this); mSocket->setPauseMode(QUdpSocket::PauseMode::PauseNever); mSocket->connectToHost(QHostAddress("192.168.1.255"), 2000); }
and I have this slot:
void UDPSender::sendPackets() { int cursor{}; while (!stopped) { if (flagData[cursor]) { for (int i{}; i < readSize / payloadLen; ++i) { memcpy(packet.data() + 4, buffer + cursor * readSize + i * payloadLen, payloadLen * sizeof(uint8_t)); if (mSocket->write(packet.constData(), packet.size()) < packet.size()) qDebug() << mSocket->error() << ", " << mSocket->errorString(); } flagData[cursor++] = false; if (cursor == nChunks) cursor= 0; } } }
flagData and buffer arrays are shared between the two classes, and I'm kinda implementing my own mutex and circular buffer.
nChunks = 512
,payloadLen = 1460
andreadSize = a * payloadLen
wherea
is an integer. I control the transmission rate witha
.When I run the program, I randomly see
QAbstractSocket::UnknownSocketError, "Unknown error"
in the console and it happens rarely (compared to the bit rate) but it's still there and the higher the bit rate, the more often I see this error. Do you have any suggestions on what the causes could be and how I can fix this? Is there any constraint on payloadLen? And what is the maximum bit rate I can achieve with connected socket in QUdpSocket? I'm using Windows 10, Qt 5.14.1.@Nastaran
Apart from your problem and @J-Hilk's suggestion (which you should try).What are you trying to achieve here with UDP? Reliable file transfer?? Are you aware of the behaviour of UDP and the (lack of) reliability for your purpose? E.g. https://cs.stackexchange.com/questions/96159/does-udp-always-deliver-packets-inorder-to-the-application-layer
Conversely from TCP, UDP does not guarantee a reliable or ordered delivery of the packets.
As the RFC states:
This protocol provides a procedure for application programs to send messages to other programs with a minimum of protocol mechanism. The protocol is transaction oriented, and delivery and duplicate protection are not guaranteed. Applications requiring ordered reliable delivery of streams of data should use the Transmission Control Protocol (TCP)
No. While UDP does deliver packets reliably 98-99% of the time, without duplicating packets 99.9% of the time, and in-order 99.9% of the time, there is absolutely no guarantee for either of these (in fact you are expected to be prepared for all of these), and reality verifiably doesn't look 100% perfect all the time.
Etc.
-
@J-Hilk This is not an endless loop. The code here is simplified. stopped will be set to true when I hit the stop button in GUI. And the compiler will not optimize it out. It is tested.
@Nastaran said in Sending UDP packets with QUdpSocket returns "UnknownSocketError" randomly:
stopped will be set to true when I hit the stop button in GUI.
that makes it for all sense and purpose an endless loop :P
did you also "simplify out" calls to processEvent() ? Also a typical cause for unexplainable errors
-
@Nastaran
Apart from your problem and @J-Hilk's suggestion (which you should try).What are you trying to achieve here with UDP? Reliable file transfer?? Are you aware of the behaviour of UDP and the (lack of) reliability for your purpose? E.g. https://cs.stackexchange.com/questions/96159/does-udp-always-deliver-packets-inorder-to-the-application-layer
Conversely from TCP, UDP does not guarantee a reliable or ordered delivery of the packets.
As the RFC states:
This protocol provides a procedure for application programs to send messages to other programs with a minimum of protocol mechanism. The protocol is transaction oriented, and delivery and duplicate protection are not guaranteed. Applications requiring ordered reliable delivery of streams of data should use the Transmission Control Protocol (TCP)
No. While UDP does deliver packets reliably 98-99% of the time, without duplicating packets 99.9% of the time, and in-order 99.9% of the time, there is absolutely no guarantee for either of these (in fact you are expected to be prepared for all of these), and reality verifiably doesn't look 100% perfect all the time.
Etc.
@JonB Thank you for the link. Yes, that's what I expected. Even though UDP does not guarantee reliable delivery, I thought there should not be any packet loss since I'm sending packets from one computer to another using an Ethernet cable (wired connection, only two computers involved! ) but that's apparently not the case.
-
@JonB Thank you for the link. Yes, that's what I expected. Even though UDP does not guarantee reliable delivery, I thought there should not be any packet loss since I'm sending packets from one computer to another using an Ethernet cable (wired connection, only two computers involved! ) but that's apparently not the case.
@Nastaran
Indeed, I wouldn't make your own assumption of how it might behave just because you have a physical direct connection!Even the Qt docs state:
It can be used when reliability isn't important.
If you are trying to use UDP because you think that's a faster way of transferring files you would not be the first person on this forum to think that is a good idea! There is a reason why file transfer programs use TCP and not UDP...!
So if you move away from UDP this question becomes moot. If you insist on sticking with it I would start by:
-
Put a
qDebug()
immediately above & below theif (mSocket->write())
. See if the intermittent error message does indeed come between these two outputs, so you know it is on that send line. -
Put a slot on
QAbstractSocket::errorOccurred()
to see when that error is emitted. -
You might also slot onto
QIODevice::bytesWritten()
to see how the data sent is being processed.
-