Implementing a TCP Server - qt

Can anyone tell me if I'm doing this right?
Using Qt I'm implementing a TCP Server by inheriting from the QTcpServer class. On an incoming connection I create a new thread, a new Worker object, and I move the object to the new thread and start the thread. From here, the server keeps listening for new clients and each thread then is in its run method for object Worker.
Now, I create a timer because I need to send updates to each client based on 1 second intervals AND when a song is playing. In the readyRead slot I read data using readAll and then perform some work and send a reply.
However, when I go back to my run method I need to just continue sending song data updates to the clients (with no response from the client). Should this all just go in a while(true) loop and then I check some boolean to start and stop the timer? The track information I need to send is the song progression time.
I guess my question is, should I be doing it this way? It seems a little complex, but then again that's concurrency for you. Basically I need the TCP server to send data to the client repeatedly when some condition is true. I feel like just an endless while loop that checks when to start and stop the timer is useless work.
Would posting code make this clearer?

This question is a very old one, but perhaps it could still help.
About threads in Qt:
Many people think about parallel processing in Qt like in .NET where you need for every operation another thread, in qt this is not necessary!
In qt you only need a thread if you have blocking code like calculating big things or waiting syncron for an answer from a SQLServer
If i have understand you correctly you don't have such a blocking operation.
So i have programmed a very small TcpServer without inheriting and without a single thread (except the main eventloop thread of course), which hopefully solves your problem and help others:
#include <QObject>
#include <QSet>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
class TcpServer : public QObject
{
Q_OBJECT
public:
TcpServer()
{
// handle new connections
this->connect(&this->serverTcp, &QTcpServer::newConnection, this, &TcpServer::handleClientConnect);
// init client refresh timer
this->timer.setInterval(1000);
this->connect(&this->timer, &QTimer::timeout, this, &TcpServer::handleClientUpdates);
this->timer.start();
}
bool startListen(qint16 port)
{
return this->serverTcp.listen(QHostAddress::Any, port);
}
private slots:
void handleClientConnect()
{
QTcpSocket* socketClient = *this->setConnectedClients.insert(this->serverTcp.nextPendingConnection());
this->connect(socketClient, &QTcpSocket::disconnected, this, &TcpServer::handleClientDisconnect);
this->connect(socketClient, &QTcpSocket::readyRead, this, &TcpServer::handleClientData);
}
void handleClientDisconnect()
{
this->setConnectedClients.remove((QTcpSocket*)this->sender());
}
void handleClientData()
{
QTcpSocket* socketSender = (QTcpSocket*)this->sender();
// handle here the data sent by the client
}
void handleClientUpdates()
{
// construct here your update data
QByteArray baUpdateResponse = "test";
// send update data to all connected clients
foreach(QTcpSocket* socketClient, this->setConnectedClients) {
socketClient->write(baUpdateResponse);
}
}
private:
QTcpServer serverTcp;
QTimer timer;
QSet<QTcpSocket*> setConnectedClients;
};

Related

QSocketNotifier warning -- using socket inside a thread

I am able to remove this warning, please suggest on below points.
QSocketNotifier: socket notifiers cannot be enabled from another thread
Whenever new request comes to QTcpServer i create new object -- xxx . This object then create thread for this socket & send receive data in
dowork_socket() function of yyy object. Inside dowork_socket() function i emit signal signalTcpSocketWriteData() to send data from socket.
Object creating the thread for new socket - xxx (I am not pasting full code):----
yyy * ptr;
QTcpSocket *m_pTcpSocket;
public slots:
void writeDataSlot( QByteArray data )
{
m_pTcpSocket->write( data );
m_pTcpSocket->flush();
}
Object in which thread is moved -- yyy (I am not pasting full code) :----
xxx *TcpSocketWrapper_ptr;
signals:
void signalTcpSocketWriteData( QByteArray);
public slots:
void dowork_socket();
Inside above object yyy contructor I am connecting signal signalTcpSocketWriteData to slot writeDataSlot :---
connect(this, SIGNAL(signalTcpSocketWriteData( QByteArray)), TcpSocketWrapper_ptr, SLOT(writeDataSlot( QByteArray )), Qt::QueuedConnection );
dowork function of object yyy :--
void TcpSocketThreadObject::dowork_socket()
{
QByteArray block;
block.append(" \n hi again .. !!!");
emit signalTcpSocketWriteData(block);
}
I am able to send data success fully by above method & above warning is removed.
1> Now my question is suppose two threads are created & both thread simultaneously emit the signal then will there be conflict in running the slot ?
2> Will it cause some critical section problem or events are queued & will not be executed simultaneously ?
Please suggest on this two points.
that seems too complicated. You don't need to create threads to work with sockets.
Whatever, if you do this, here's two points needs to be kept in mind:
QTcpSocket is Not thread-safe itself
as long as you use Qt::QueuedConnection when connecting slot (or at least proper using of implicit connections between different threads do this) all code executing inside connected slot will be execited in object's thread loop. In other words, signals emitted from different thread(s) will be queued.

Qt how doing a blocking wait until receiving data

I have a qt program. I have CAN requests that I want to send in sequential order.
I want to wait for answers, before sending other requests.
SendReadLatchCommand(fam,prod,addr,0x00000000, 4); // 1st request
// wait for answer and analyze it??
SendReadLatchCommand(fam,prod,addr,0x00000002, 4); // 2nd request
I have a receiveData() method, called by my thread of reception, where I save the received message.
I want to sleep in my main program and we awake when receiving answer.
I can't use signal/slot because in the slot, I don't know what is the last request I sent, so I can't continue emitting requests.
How can I do this?
thanks
If i understand you properly, you wanted to process the request synchronously.
Look into the QEventLoop in the qtdoc, you can do it this way:
QEventLoop wait_loop;
// 1st request
connect(request_1, SIGNAL(sig_answer_arrived()), &wait_loop, SLOT(quit()));
request_1->send_request();
wait_loop.exec();
// here we already got the answer
analyze_answer();
// the 2nd request does the same
I'm not sure whether it is a good idea to block your main thread, however it can be done by using a binary semaphore, which is the same as a counting semaphore with a maxCount of 1. Therefore one can use a counting semaphore QSemaphore
Typically, a QSemaphore is implemented in terms of QWaitCondition (refer Qt help). One could block on a wait condition until the CAN thread signals the wait condition. One can hide the blocking on the wait behind some interface e.g:
//--- Very simple implementation - concept only
QWaitCondition cond_;
QMutex mutex_;
void rxThreadHandler( /*args*/ )
{
while( !quitCalled() )
{
waitOnReceivedData();//Blocks, I assume...
handleReceivedData();
answerRxd();
}
}
void answerRxd()
{
QMutexLocker lock( mutex_ );
cond_.wakeAll();
}
void sendNext( const Buffer& buffer )
{
QMutexLocker guard( mutex_ );
//Waits/Blocks until condition signalled, then locks mutex
// to prevent further signalling (might block rx thread)
cond_.wait( lock.mutex() );
//Unlocking mutex explicitly to allow receipt of data
guard.unlock();
//Now send as result of previous receive. This does not
// prevent receiving thread...
sendNextImpl( const Buffer& buffer );
}

Qt Signals and slots mechanism blocked by a loop in main

I have a following situatuion.
2 Socket objects are created in the main in a for loop (the original problem has 1000 objects). Upon creation the start() method is invoked.
start() creates a QTcpSocket which tries to connect to some host.
Socket has slots which catch the connected() signal from QTcpSocket and print some debug output
What happens is that chronologically first ALL the Socket objects are created after which the sockets are started. Here is an example output of debug options:
1. Created Socket object 1
2. Invoked Socket object 1 start()
3. Created Socket object 2
4. Invoked Socket object 2 start()
5. Socket object 1 TcpSocket Connected
6. Socket object 2 TcpSocket Connected
Code:
//main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
for (int i=0; i<10; i++)
{
Socket *socket = new Socket();
qDebug() << "Socket object created";
socket->Start();
}
return a.exec();
}
//socket.cpp
Socket::Socket(QObject *parent)
: QObject(parent)
{}
void Socket::Start()
{
qDebug()<<"Start method invoked";
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()), this, SLOT(on_connect()), Qt::DirectConnection);
socket->connectToHost("192.168.5.5",12345);
}
void Socket::on_connect()
{
QTcpSocket* socket = qobject_cast<QTcpSocket *>(QObject::sender());
qDebug() << socket->socketDescriptor() << " Connected.";
}
This is not the behavior I expected because the documentation states:
When a signal is emitted, the slots connected to it are usually
executed immediately, just like a normal function call. When this
happens, the signals and slots mechanism is totally independent of any
GUI event loop.
Question:
How to ensure the slots are executed "immediately" (not only after the loop in the main finishes) when the signal is emitted?
The only available solution (without introducing new threads) i currently see:
Drop the use of signals and slots in this case, and implement everything in the start method. Something like this:
Socket::start(){
...
if(!tcpsocket->waitForConnected(200)) qDebug() << "Socket object X TcpSocket Connected"
...
}
Your slot is indeed triggered immediately when QTcpSocket's signal connected() is emitted.
However, connected() is not emitted the moment you try to connect that socket to somewhere.
The documentation writes:
This signal is emitted after connectToHost() has been called
and a connection has been successfully established.
The establish of a connection requires an event loop.
establishing the connection happens asynchronously (read connectToHost will return immediately before it even checks whether the connection has already been established) and will notify your code using the signals that are triggered by events
these events are handled only in the event loop or when you call WaitForConnect (which will spin up it's own even loop only handling those events)
this means that the sequence you get is perfectly normal
I don't think you can do that without introducing new threads, only solution is seems your solution.
Or using DirectConnection instead of leaving it empty (Which is AutomaticConnection and which is QueuedConnection in your case) may be a solution. But I don't think that it will work because you need to wait in order to run that slot. I'm not sure, just give it a try.

How to implement "first come first served" scheduling algorithm using threading in Qt C++ programming?

I wish to add processes to a dynamic list then schedule those processes using the "first come first served" scheduling algorithm. The scheduling algorithm should only run a max of 5 processes concurrently and when a process has been terminated it should it should emit a signal to indicate termination.
Then when a process has been terminated, another process should be scheduled by the scheduling algorithm once there are processes in the queue.
Note also that each process has access to a shared list of integer which only one process can access at a time. I already know how to do this part by locking the shared integer list using QMutex. Ideally, I am seeking an example, so I can understand it.
//mutex example
QMutex mutex
while(!mutex->tryLock()){
//enter code here
}
this->performTask(); //
mutex.unlock();
You will have 5 instances of a class that extends QThread. Each class will execute a QProcess and wait for it to finish.
class MyThread : public QThread
{
public:
MyThread(MyScheduler& aScheduler)
: iScheduler(aScheduler)
{
}
void ExecuteProgram(const QString& aProgramName)
{
iProgramName = aProgramName;
start();
}
void run()
{
iProcess.start(iProgramName);
iProcess.waitForFinished(-1);
iScheduler.SignalProgramTerminated(this);
}
private:
MyScheduler& iScheduler; // This is your FCFS scheduler.
QString iProgramName;
QProcess iProcess;
};
(I haven't compiled this but it should give you some headway).
You could use QThreadPool to create a pool of 5 threads that run your processes and use QQueue to queue the pending processes in a FIFO fashion.
edit:
About mutexes:
The mutex protects a piece of code form beeing executed by more than one thread. A thread tying to lock a mutex will be blocked until no other thread holds the lock. The easiest way to use mutexes is with the QMutexLocker.
void myclass::modifyList(IntegerList* list)
{
QMutexLocker lock(list->getMutex()); //this will block if an other thread holds the mutes
//do stuff
}

Qthread - trouble shutting down threads

For the last few days, I've been trying out the new preferred approach for using QThreads without subclassing QThread. The trouble I'm having is when I try to shutdown a set of threads that I created. I regularly get a "Destroyed while thread is still running" message (if I'm running in Debug mode, I also get a Segmentation Fault dialog). My code is very simple, and I've tried to follow the examples that I've been able to find on the internet.
My basic setup is as follows: I've a simple class that I want to run in a separate thread; in fact, I want to run 5 instances of this class, each in a separate thread. I have a simple dialog with a button to start each thread, and a button to stop each thread (10 buttons). When I click one of the "start" buttons, a new instance of the test class is created, a new QThread is created, a movetothread is called to get the test class object to the thread...also, since I have a couple of other members in the test class that need to move to the thread, I call movetothread a few additional times with these other items. Note that one of these items is a QUdpSocket, and although this may not make sense, I wanted to make sure that sockets could be moved to a separate thread in this fashion...I haven't tested the use of the socket in the thread at this point.
Starting of the threads all seem to work fine. When I use the linux top command to see if the threads are created and running, they show up as expected.
The problem occurs when I begin stopping the threads. I randomly (or it appears to be random) get the error described above.
Class that is to run in separate thread:
// Declaration
class TestClass : public QObject
{
Q_OBJECT
public:
explicit TestClass(QObject *parent = 0);
QTimer m_workTimer;
QUdpSocket m_socket;
Q_SIGNALS:
void finished();
public Q_SLOTS:
void start();
void stop();
void doWork();
};
// Implementation
TestClass::TestClass(QObject *parent) :
QObject(parent)
{
}
void TestClass::start()
{
connect(&m_workTimer, SIGNAL(timeout()),this,SLOT(doWork()));
m_workTimer.start(50);
}
void TestClass::stop()
{
m_workTimer.stop();
emit finished();
}
void TestClass::doWork()
{
int j;
for(int i = 0; i<10000; i++)
{
j = i;
}
}
Inside my main app, code called to start the first thread (similar code exists for each of the other threads):
mp_thread1 = new QThread();
mp_testClass1 = new TestClass();
mp_testClass1->moveToThread(mp_thread1);
mp_testClass1->m_socket.moveToThread(mp_thread1);
mp_testClass1->m_workTimer.moveToThread(mp_thread1);
connect(mp_thread1, SIGNAL(started()), mp_testClass1, SLOT(start()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(quit()));
connect(mp_testClass1, SIGNAL(finished()), mp_testClass1, SLOT(deleteLater()));
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
connect(this,SIGNAL(stop1()),mp_testClass1,SLOT(stop()));
mp_thread1->start();
Also inside my main app, this code is called when a stop button is clicked for a specific thread (in this case thread 1):
emit stop1();
Sometimes it appears that threads are stopped and destroyed without issue. Other times, I get the error described above.
Any guidance would be greatly appreciated.
Thanks,
Bryan
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
"Finally, to prevent nasty crashes because the thread hasn’t fully shut down yet when it is deleted, we connect the finished() of the thread (not the worker!) to its own deleteLater() slot. This will cause the thread to be deleted only after it has fully shut down."
Please try replacing:
connect(mp_testClass1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));
with:
connect(mp_thread1, SIGNAL(finished()), mp_thread1, SLOT(deleteLater()));

Resources