Qt TCP server/multi-client message reading - c++

I am working on a client/server application (using qt for tcp).
The clients have to send about 15 messages per second to the server.
The problem is this:
the messages from the clients are received in groups. What i mean:
when i get the readyRead() signal and i read the data from the socket, there are multiple messages in the buffer.
This of-course causes lag in the system.
I tried putting the incoming connections in separate threads (thread per connection) but there was no improvement.
I also tried to rise a thread each time i got a readyRead() signal, but again nothing...
BUT when i run a number of clients on the same pc as the server, everything seems ok. When using different pc's over the network, the lag occurs...
(the network used is 100Mbps LAN, the messages are <200KB, and ping between pc's is <5msec, so i don't believe it's a network issue)
On the client side, the code to write the data is pretty simple:
tcpSocket->write(message.toUtf8());
tcpSocket->waitForBytesWritten();
tcpSocket->flush();
I also tried it without flush() or waitForBytesWritten() but the same...
EDIT: Using Qt 4.8.4 and Windows 7 and XP
Anybody has any idea how to overcome this?
Thank you in advance!

The last time I ran into a similar problem was with the stdin/stdout communication of a QProcess of Qt3.3. It behaved completely different on Linux and Windows.
Finally we found out that on Linux it used select() to react asynchronously when data arrived (fast, in most cases only one line readable) while on Windows the existence of new data was polled via a QTimer from the Qt mainloop (large delay, several messages available). A workaround we tried was to reduce the timer period in the source of Qt, but at the end we switched to shared memory based on the native OS mechanisms.
Your description sounds like you are using a similar Qt version on a Windows OS.

Related

How to use a single Boost::asio::io_context for multiple sockets and serial ports

I'm using Boost::Asio to create multiple UDP sockets and serial ports, and I use a single boost::asio::io_context that is shared among all of them (given in the constructor). All devices are configured to run with async reads and writes. Then, I only call io_context.run(); to let it run forever. It works very well most of the time.
However, at some point, for example when a sudden traffic load reaches one socket, my process suddenly jumps to 100% on the CPU and stays at 100% forever, with the global communication dying. When this happens, using perf, I see that the process is stuck 99.99% of the time at the same place, with a stack looking like:
main
asio::detail::scheduler::run
asio::detail::epoll_reactor::descriptor_state::do_complete
asio::descriptor_read_op<asio::mutable_buffers_1, std::_Bind<void
my_serial_port::on_async_data_received <- this is my receiving function for serial ports
...
So it seems that it is stuck processing only one serial port in loop, but nothing else anymore, as if a same event was processed endlessly, while there is still a lot of other data coming in the system.
Is there something I'm doing wrong by sharing the io_context ?
Is there a way to debug such issues with events with Boost::Asio ?
I have seen a similar hang, but where the stack only shows a function called by a timer event instead of the serial port (i.e. a timer sending a statistics packet at 1 Hz, but taking 100% of the CPU and blocking everything else).
Context:
On an embedded system using ROS and Linux, I'm running a process (ROS node) that acts as a communication router. It has 7 inputs/outputs: 2 serial ports (3 Mb/s), 2 network UDP sockets and 3 local UDP sockets (UNIX domain). It also listens to some ROS topics coming from other processes.
Packets can be received on all ports and a custom protocol is used to decode the packets, read their destination and send them out further on the given port. Some packets are also generated in the process and sent out on some ports, based on data subscribed through ROS.
To keep things simple, to avoid concurrency and because I only have one core available, I try to run this process on a single main thread.
To merge ROS and Boost::Asio together in a single thread, I'm using librosasio to forward events from ROS to the asio::io_context.
Thanks !
The BOOST_ENABLE_HANDLER_TRACKING may give you some insight into where the problem lies.

Qt EventLoop delay with high frequency signal<->slot connections

I'm really going crazy over this and I hope somebody has an answer...
I do encounter a strange problem with QUdpSockets and the Signal and Slot Connection. I'm receiving small data packets (64 bytes) at 3 different UdpSockets with 100Hz without any processing afterwards. The Signal<-> Slot Connection for reading out the data seams to work completly fine on different laptops, but not on the pc it is supposed to run in the end, which has way more processing power than the laptops.
I'm running the same code on every machine with the same setup. The Problem is, the recvEvents are somehow being queued and delayed up to several seconds on the pc, but not on the laptops. At first I thought It would be a network issue, but I already tried different network cards/switches etc.. and several other things. The only thing that helped is changing the receive code from signal<->slots to another thread with std::thread, so it definitely has to do something with the connection from the readyRead signal.Some Code:
connect(&udpSocket, &QUdpSocket::readyRead, this, &DataController::handleData);// Called with 100Hz
void handleData(){ //This function call is beeing delayed/queued....
udpSocket.readDatagram(&data,datasize);
}
My Question:
Is there any limit of Events/seconds which can be handled?
Do you have any suggestion where I can look for errors or how to
speed up the QEventLoop?
Im Running:
Win10 Pro, VS 2017 64bit,Qt 5.11.2
BR
mike
Obviously, with slower computers you always have only one datagram waiting for reading. With faster computer you may have received more than one by the time you are in your slot reading. You should always read all pending datagrams when you receive readyRead signal. You can use QUdpSocket::hasPendingDatagrams for that.
void handleData(){
while (udpSocket.hasPendingDatagrams()) {
// clear data buffer
udpSocket.readDatagram(&data,datasize);
// process received datagram before reading next...
}
}

Should I receive all messages after QLocalSocket is disconnected?

I have an application in c++/Qt in Windows, Linux and MacOSX, and I have a local client-server mechanism using Qt Local Server/Socket.
When the server refuses a connection, I send a message and close the socket, using QLocalSocket::disconnectFromServer()
From the documentation I see
If there is pending data waiting to be written, QLocalSocket will enter ClosingState and wait until all data has been written.
So in the client side, I connect the signal QLocalSocket::disconnected and do the following in my slot
void MyClientClass::onSocketDisconnected()
{
qDebug() << "Socket disconnected";
socket->readAll();
//I do something with the data read
}
But it happens that sometimes, mostly on slow Linux machines (I try with virtual machines with only 1 processor), I do not receive the last message that the server send just before closing.
Why this happens? It should be in contrast with the documentation, shouldn't it?
Is there some motivation why I noticed it only in Linux and MacOSX (where Qt uses unix domain sockets) and I did not noticed it in Windows (where Qt uses pipes)?
Maybe there is some motivation related to domain sockets? Or I just misunderstood something?
Edit: as written in the comments below, in these cases when I do not receive the message, also the QLocalSocket::ClosingState is missing and I receive directly the QLocalSocket::UnconnectedState
Edit 2: as suggested in comments, I tried the waitForReadyRead() function. I did it onSocketDisconnected() and also onStateChanged() when the state goes to QLocalSocket::ClosingState or QLocalSocket::UnconnectedState. When I receive the QLocalSocket::ClosingState everything goes well, but the problem, as I said in the last edit, is that sometimes QLocalSocket::ClosingState is missing. In this case, the waitForReadyRead() fails without waiting the timeout and I have a warning "QIODevice:read (QTcpSocket): device not open" (even if I am using QLocalSocket, maybe the warning message is not updated well in Qt source). By the way, I am using Qt5.7.

threaded serial port communication in C++ with Qt

I am writing an QT desktop application that is going to display information received from a serial port. Therefore a class was created and packed into an DLL using standard Windows API features to communicate with the connected device (CreateFile, ReadFile, WriteFile, ...).
At the moment a timer calls the DLL at a predefined rate [< 200ms] and this leads the gui to freeze for short periods. Because of that i am thinking of using a thread to do the serial port stuff, that is also going to display everything.
Is is better to use threads for this problem or should i rewrite the class to do the work event based? The target is, that the gui doesnt freeze.
Edit:
I solved the problem using a QThread derived worker class with an overshadowed run() function, that handles the serial port communication in the background and updates the gui as new informations are available.
It is good practice in many use cases to do all blocking (synchronous) I/O on a separate thread, especially when a graphical user interface is involved. Here's a page I've referenced regarding the challenges with synchronous I/O (as opposed to asynchronous where your code doesn't block but is still single-threaded, or parallel as you're discussing). There are more issues than just what you brought up, for example:
What if there is no data available? Does the GUI block until there is data? For example, if the sender was off then there would be no data
What does the program do if the I/O device is no longer available? For example, if it is a USB-to-serial adapter, what happens if the adapter is unplugged?

Non blocking threaded tcpi client in Qt

Please let me explain what is my problem:
I have a Gui application, that has to connect to remote server and keep connected to it for the time untill a user decides to quit the connection, or the server will. I wish to create the client connection mechanism in a separate thread. If the client should be able to asynchronusly receive data and in event driven style inform the main gui thread about it. The thread should also be able to receive data from gui thread to be sent to the server.
I come from a low level microcontroller place, where I would handle this task simply using interrupts and while(1) loop and flags. The problem is on a pc, this would take to much processor time. I have watched and read a lot of tutorials about sockets and threads in qt, but i still dont know what is the best aproach and how to do it properly.
For now, I have a test server on a remote target that is able to receive connections from my Qt client that I am trying to write. I have a class now for my client in Qt, that inherits from Qthread, but then I read that it is not the best aproach anymore.
I wish to create a client instance in new thread (triggered from the gui thread) that will hang forever with exec(). Now I dont know how to handle, using signals the incoming data from the server and incoming commands from the main GUI thread. In general, I would maybe know how to implement this on a low level, but i read about a lot of high level functions for this that qt delivers, i wish to use that.
I would really aprichiate help in this matter. I tried searching, but havent found any solid, working up to date code examples. Could someone please explain me how to create a client instannce in a new thread that wont disconnect after sending/ receiving some data, but instead stay connected and stay responsive to to server calls and gui thread calls in event driven style?
May be use general Qt socket mechanism instead separate thread will be better for you. Sockets is very similar to MCU interrupts and simple to use. For your application requests it must be enough.