Signals are received twice in OMNet++ - c++

I have created my own OMNet++ Listener class as follows:
headerfile
#ifndef MYFRAMELISTENER_H_
#define MYFRAMELISTENER_H_
#include <clistener.h>
#include <vector>
class MyFrameListener : public cListener{
public:
int tempDelmeJustForTest;
simsignal_t signalIDArray[14];
int index;
public:
MyFrameListener();
virtual ~MyFrameListener();
virtual void receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj);
};
#endif /* MYFRAMELISTENER_H_ */
cc File
MyFrameListener::MyFrameListener() {
this->tempDelmeJustForTest = 0;
}
MyFrameListener::~MyFrameListener() {
}
void MyFrameListener::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj){
tempDelmeJustForTest++;
}
SimpleModule cc file:
void ListenersModule::initialize()
{
// TODO - Generated method body
frameListener = new MyFrameListener();
//subscribe("packetReceivedFromLower",frameListener);
simulation.getSystemModule()->subscribe("packetReceivedFromLower",frameListener);
}
void ListenersModule::handleMessage(cMessage *msg)
{
// TODO - Generated method body
}
void ListenersModule::finish(){
//simulation.getSystemModule()->unsubscribe("packetReceivedFromLower",frameListener);
recordScalar("My Listened Values", this->frameListener->tempDelmeJustForTest);
}
Here, I am trying to count the number of Ethernet frames received in EtherMACFullDuplex by incrementing the tempDelmeJustForTest variable.
EtherMACFullDuplex is a module located in inet/src/inet/linklayer/ethernet/EtherMACFullDuplex.cc and it is used to create the Ethernet phy port.
This class has a function as shown below:
void EtherMACFullDuplex::processReceivedDataFrame(EtherFrame *frame)
{
emit(packetReceivedFromLowerSignal, frame);
// strip physical layer overhead (preamble, SFD) from frame
frame->setByteLength(frame->getFrameByteLength());
// statistics
unsigned long curBytes = frame->getByteLength();
numFramesReceivedOK++;
numBytesReceivedOK += curBytes;
emit(rxPkOkSignal, frame);
numFramesPassedToHL++;
emit(packetSentToUpperSignal, frame);
// pass up to upper layer
EV_INFO << "Sending " << frame << " to upper layer.\n";
send(frame, "upperLayerOut");
}
It emits a signal "packetReceivedFromLower" and my listner has subscribed to it as shown in the above code.
Problem is the counter shows tempDelmeJustForTest = 12 when the sender sends only 6 Ethernet Frames. Why ?
Also, I am project referencing Core4Inet project other than the Inet project.

I am guessing you are overhearing the signal emitted by the MAC layer of the destination host and the MAC layer of the switch.
By subscribing not just at your own module, but at the module returned by simulation.getSystemModule(), you are overhearing all signals of type packetReceivedFromLower emitted anywhere in the simulation. The "Subscribing to Signals" chapter of the user manual has more information on this mechanism.
If you want to know where the signal you are overhearing was emitted from, you can use the source parameter of your receiveSignal method.

The counter tempDelmeJustForTest shows 12 when the sender sends 6 Ethernet Frames, because the method processReceivedDataFrame is involved 6 times in your switch and 6 times in destination host.
The command:
simulation.getSystemModule()->subscribe("packetReceivedFromLower",frameListener);
means that the listener will receive the signal from any element (i.e. including switch). You can check which module sent a signal by adding one line in receiveSignal():
void MyFrameListener::receiveSignal(cComponent *source, simsignal_t signalID, cObject *obj){
EV << "Signal from " << source->getFullPath() << endl;
tempDelmeJustForTest++;
}

Related

Omnet++ : Generate packets from the source node and receive acknowledgement packet from the destination node

Three nodes Node1, Node2 and Node3 are connected in point to point fashion as - Node1-->Node2-->Node3.
Node1 is the source node and generates packets at the rate of 50 packets/sec. Node2 simply forwards the packets to Node3 which is the destination node. And Node3 deletes all the packets, and for every tenth packet received by Node3 it sends an acknowledgement packet back to Node1.
I have written the following code for the given problem setup-
.cc file
class communicate : public cSimpleModule
{ public:
cMessage *timer;
cMessage *data;
protected:
virtual void forwardMessage(cMessage *msg);
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;};
Define_Module(communicate);
void communicate::initialize()
{
if (getIndex() == 0) {
timer=new cMessage();
scheduleAt(0.0, timer);
}
}
void communicate::handleMessage(cMessage *msg)
{ int count=0;
if (msg == timer){
data=new cMessage("hello");
EV<<"NEW PACKET GENERATED getIndex()\n";
forwardMessage(data);
scheduleAt(simTime()+0.01, timer);
}
else {
if(getIndex()==1)
{
forwardMessage(data);
}
else
{
EV<<"MESSAGE ARRIVED AT DESTINATION\n";
delete data;
}
}
}
void communicate::forwardMessage(cMessage *msg)
{ if(getIndex()==0)
{
send(msg,"out1");
}
else(getIndex()==1)
{
send(msg,"out2");
}
}
and the corresponding .ned file-
simple communicate
{
parameters:
#display("i=block/routing");
gates:
input in1;
input in2;
output out1;
output out2;
}
network fournodes
{
#display("bgb=130,142");
submodules:
tic[3]: communicate;
connections:
tic[0].out1 --> { delay = 1ms; } --> tic[1].in1;
tic[1].out1 --> { delay = 1ms; } --> tic[0].in1;
tic[1].out2 --> { delay = 1ms; } --> tic[2].in1;
tic[2].out1 --> { delay = 1ms; } --> tic[1].in2;
}
For the above written code, I am getting the following error after execution--
send()/sendDelayed(): Message pointer is nullptr -- in module (communicate) fournodes.tic[1] (id=3), at t=0.001s, event #2
Please point out the mistake that I have made in this code or suggest some alternate way to solve the problem. Thanks in advance for any help.
First of all, you should precise how the node that receives a message determines whether and where forward that message. In tictocMsg you have declared source and destination but these fields are not checked anywhere.
I suggest assuming some rules for "routing" messages in the network. For example, it may be assumed that:
Every node has own Address (e.g. tic[0] - has address 0, tic[1] - 1, etc.).
Every node has a static "routing" table. The table is filled in advance. For example, the table for tic[1] may look like:
Destination address
Index of out gate
0
0
2
2
When the node receives a message, it checks whether destination from this message is equal to own address. If no - message is forwarded via the gate selected from the table. If yes - message is processed locally.

Wire.onReceive() function on Arduino

I am trying to take what is in this example given by the Arduino Wire library, and apply it to a program I am writing.
This is my code. The Comm.NDP[] statements are other class instances not saved in this file, so I believe you can ignore them.
**
* I2C.cpp handles sending of event messages
* between the LORA and MEGA via I2C protocol.
*/
#include "I2C.h"
#include "DATA.h"
#include "Globals.h"
#include <Wire.h>
#include <Arduino.h>
/**
* Constructor used to reference all other variables & functions.
*/
I2C::I2C() {
}
/**
* Assigns the proper address to the current micro controller.
*/
void I2C::initialize() {
//Sets the address for the current micro controller.
// Mega - 0
// LoRa - 1
Wire.begin(0);
Wire.setClock(8000000);
//Registers recieveEvent as a interrupt.
Wire.onReceive(receiveEvent); // register event
}
/**
* Receives byte over I2C Connection.
*/
static void receiveEvent(int howmany) {
//Iterator used below.
int i = 0;
for(i=0;i<120;i++) {
Comm.NDP[i] = ' ';
}
//Resets iterator.
i = 0;
//Checks to see if serial port is empty.
while (1 < Wire.available()) {
//Reads in single character from serial port.
char character = Wire.read();
NDP[i] = character;
i++;
}
Serial.println(Comm.NDP);
}
The example code from Arduino's Wire.h library
#include <Wire.h>
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop() {
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
while (1 < Wire.available()) { // loop through all but the last
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
I am getting this error from the Arduino IDE.
error: invalid use of non-static member function
Wire.onReceive(receiveEvent); // register event
^
exit status 1
invalid use of non-static member function
You're missing declaration of receiveEvent before first use. Either move it's definition before begin or add there:
void receiveEvent(int howMany);

QMediaPlayer Not Loading Media And Not Emitting mediaStatusChanged() Signals

I've recently started working with Qt and am trying to play a sound file using QMediaPlayer.
My program compiles and runs but the sound file is not played, the QMediaPlayer seems stuck in the QMediaPlayer::LoadingMedia state.
Also - and possibly related - the QMediaPlayer doesn't ever seem to emit its mediaStatusChanged or its error signals (though perhaps this is me not connecting them properly?)
When I run the program as below, it reaches the while loop and never leaves. If I query for player->mediaStatus() inside the loop, it constantly returns 2 (QMediaPlayer::LoadingMedia).
When I run it with the while loop omitted, the program continues to run until it reaches end of execution with no run-time errors but - as you may expect - the file is not played.
Interestingly, the two couts before the while loop, which report player's mediaStatus and state show that the mediaStatus changes from 1 (in the first instance, before setting the media) to 2 (after setting the media) but my ChangedStatus slot is never called, despite connecting to the mediaStatusChanged at the start of the run function.
Running: Debian Jessie, Qt5.7/Qt5.9
AudioPlayer.h
#include <QThread>
#include <QMediaPlayer>
class AudioPlayer : public QThread {
Q_OBJECT
public:
AudioPlayer();
public slots:
void ChangedStatus(QMediaPlayer::MediaStatus);
void MediaError(QMediaPlayer::Error);
protected:
void run();
};
AudioPlayer.cpp:
AudioPlayer::AudioPlayer(){}
void AudioPlayer::run()
{
QMediaPlayer* player = new QMediaPlayer();
connect(player, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)), this, SLOT(ChangedStatus(QMediaPlayer::MediaStatus)));
connect(player, SIGNAL(error(QMediaPlayer::Error)), this, SLOT(MediaError(QMediaPlayer::Error)));
std::cout << "Got player!" << std::endl;
std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;
player->setMedia(QUrl::fromLocalFile("/home/me/test.wav") );
std::cout << "Set source" << std::endl;
std::cout << "\n\n\tPlayer state: " << player->state() << "\n\tMediaState: " << player->mediaStatus() << std::endl;
while(player->mediaStatus() != QMediaPlayer::MediaStatus::LoadedMedia)
{//
}
player->setVolume(100);
std::cout << "Set volume" << std::endl;
player->play();
std::cout << "Played" << std::endl;
}
void AudioPlayer::MediaError(QMediaPlayer::Error error)
{
std::cout << "Media Error: " << error << std::endl;
}
void AudioPlayer::ChangedStatus(QMediaPlayer::MediaStatus status)
{
std::cout << "Status changed to: " << status << std::endl;
}
main.cpp:
#include "audioplayer.h"
using namespace std;
int main()
{
cout << "Hello World!" << endl;
AudioPlayer myAudioPlayer;
myAudioPlayer.start();
std::cout << "myAudioPlayer started. Waiting...." << std::endl;
myAudioPlayer.wait();
std::cout << "myAudioPlayer returned." << std::endl;
return 0;
}
Extra Info:
Now, initially, I hadn't used QThread and was trying to do this all in main.cpp (just declaring a QMediaPlayer and attempting to set the media and play) but this was giving me QObject::startTimer: timers cannot be started from another thread warning run-time errors in a couple of places (declaration of the QMediaPlayer and, I think, the play command), so I adopted the above approach - although I'm not sure that subclassing QThread is, necessarily, the best way. This is also why everything (declarations etc.) is done in the run function - having the QMediaPlayer as a member of AudioPlayer and initialising it in the constructor gave the same error.
I have compiled and run Qt's Player example (from multimediawidgets) and, by browsing and selecting my test.wav, it can play the file so I don't think it's a compatibility issue. I looked through the Player example source but couldn't see anything jumping out which I had missed and which looked like the cause of my problem.
You should create an QApplication object and use it's message loop. I would suggest you to test following:
#include "audioplayer.h"
using namespace std;
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
AudioPlayer myAudioPlayer;
myAudioPlayer.start();
return a.exec();
}
You will at least get your signals raised. If the media state reaches QMediaPlayer::StoppedState or any error occured, you could call QApplication::instance()->quit() to stop your application.
Edit: Better use the new style connections like:
connect(player, &QMediaPlayer::mediaStatusChanged, this, &QMediaPlayer::ChangedStatus);
It is more reliable and you don't have to register specific parameter types like QMediaPlayer::MediaStatus with Q_DECLARE_METATYPE()
Because QMediaPlayer class contains another method called error with a different signature, signal connection is a bit more complicated. This is because the compiler don't know which error method you are referring to. In this case static_cast is the way to solve this ambiguity:
connect(
player,
static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error )>(&QMediaPlayer::error),
this,
&AudioPlayer::MediaError
);
Please note, a Wave file is only a container file that can contain an arbitrary compressed data stream. It may be necessary to install the appropriate operating system multimedia codec first. In Microsoft Windows Qt-Framework relies on installed multimedia codecs (.ax file).
Your AudioPlayer::run method will end without waiting for the media being played. So you should wait for the Stopped status some where before the thread ends. However it is better not to use the run method directly but using QThreads message loop instead.
class AudioPlayer : public QThread {
public:
AudioPlayer() : _Player(nullptr) {
moveToThread(this); // AudioPlayer object become part of this new thread
}
public slots:
void setVolume(int);
void load(QString Media);
// ...
void play() {
// Never directly access any members since they may belong to a different thread
if (thread() != QThread::currentThread()) {
QMetaObject::invokeMethod(this, "play", Qt::QueuedConnection);
} else {
_Player->play();
}
}
void stop() {
quit(); // Quiting thread message loop
}
private:
QMediaPlayer* _Player;
void run() {
_Player = new QMediaPlayer(this);
connect(...) // All connections go here...
int Result = QThread::exec();
_Player->stop();
delete _Player;
}
private slots:
void HandleStatusChange(QMediaPlayer::MediaStatus Status) {
emit statusChanged(Status); // Redirect so that the main application can handle this signal too
}
signals:
void statusChanged((QMediaPlayer::MediaStatus);
};

readAll() from QSerialPort doesn't include the last response sent

I'm using Qt to control a serial device. If I send a command to my serial device, I do something like serial->write("command \r\n"). I made a push button which changes the text inside a plain text widget to the response of the serial port. To get the response of the serial port, I'm using serial->readAll(). The problem is it shows the 2nd to last response rather than the one I was expecting. Does Qt have some sort of buffer which is keeping hold of this response?
EDIT
I botched it by using recursion and compared the strings recieved
You might be calling readAll before the response is available. You should hook your code to the readyRead signal to be notified each time new chunk of data is ready to be read. Keep in mind that readyRead can be emitted with any number of bytes available to read - at a minimum, it'll be just one byte. You can't expect the data to be chunked/blocked in any particular way, since the serial port doesn't act as a message-based communication device. Your receiver code must be able to piece the data together from small chunks and act accordingly when it got all the data it needs.
For example, suppose that the device responses have a fixed, known length. You'd only want to react when a complete response has arrived. E.g.:
class Protocol : public QObject {
Q_OBJECT
QBasicTimer m_timer;
QPointer<QIODevice> m_port;
int m_responseLength = 0;
int m_read = 0;
void timerEvent(QTimerEvent * ev) override {
if (ev->timerId() != m_timer.timerId()) return;
m_timer.stop();
emit timedOut();
}
void onData() {
m_read += m_port->bytesAvailable();
if (m_read < m_responseLength)
return;
m_timer.stop();
emit gotResponse(m_port->read(m_responseLength));
m_read -= m_responseLength;
m_responseLength = 0;
}
public:
Q_SIGNAL void gotResponse(const QByteArray &);
Q_SIGNAL void timedOut();
Q_SLOT void sendCommand(const QByteArray & cmd, int responseLength, int cmdTimeout) {
m_responseLength = responseLength;
m_port->write(cmd);
m_timer.start(cmdTimeout, this);
}
explicit Protocol(QIODevice * port, QObject * parent = nullptr) :
QObject(parent), m_port(port) {
connect(m_port, &QIODevice::readyRead, this, &Protocol::onData);
}
};
...
Protocol protocol(0,0);
protocol.sendCommand({"foo"}, 10, 500);
QMetaObject::Connection cmd1;
cmd1 = QObject::connect(&protocol, &Protocol::gotResponse, [&]{
QObject::disconnect(cmd1);
qDebug() << "got response to foo";
});
QObject::connect(&protocol, &Protocol::timedOut, []{ qDebug() << "timed out :("; });

Qt QTcpSocket() readReady Signal never fires (slot never called) in multithreaded Server applicaton. waitForReadyRead() method works fine

I'm writing a threaded TcpServer (each client in its own thread) using QTcpServer and QTcpSocket. The client application works correctly and sends data every 3 seconds but the readReady() signal never fires, meaning my receive_data() function is never called. When using socket->waitForReadyRead() and calling receive_data() by myself everything works fine. Please have a look at the code below, maybe I made some mistake with the moveToThread / connect functionality Qt offers.
Client.h
#ifndef CLIENT_H
#define CLIENT_H
#include <QThread>
#include <QTcpSocket>
#include <QHostAddress>
#include "PacketDefinitions.h"
#include "tcpserver.h"
class Client : public QObject
{
Q_OBJECT
public:
explicit Client(int socket,TcpServer *parent,bool auto_disconnect = true);
~Client();
bool isGameServer(){return is_gameserver;}
GameServerPacket getGameServerData(){return gameserver;}
void run();
private:
QTcpSocket* client;
TcpServer *parent_server;
int socket;
GameServerPacket gameserver;
ClientPacket clientdata;
bool is_gameserver;
bool auto_disconnect;
QHostAddress client_ip;
quint16 client_port;
signals:
void disconnected(Client *);
private slots:
void remove_from_clientlist();
void receive_data();
void display_error(QAbstractSocket::SocketError error);
};
#endif // CLIENT_H
Client.cpp
#include "client.h"
#include "PacketDefinitions.h"
#include "time.h"
#include <iostream>
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
auto_disconnect = _auto_disconnect;
parent_server = parent;
is_gameserver = false;
socket = _socket;
}
void Client::run(){
client = new QTcpSocket();
if(client->setSocketDescriptor(socket) == false){
std::cout << client->errorString().toStdString() << std::endl;
remove_from_clientlist();
return;
}
connect(client,SIGNAL(disconnected()),this,SLOT(remove_from_clientlist()));
if(connect(client,SIGNAL(readyRead()),this,SLOT(receive_data()),Qt::DirectConnection) == false) return;
connect(client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(display_error(QAbstractSocket::SocketError)));
client_ip = client->peerAddress();
client_port = client->peerPort();
std::cout << "New incomming connection " << client->peerAddress().toString().toStdString() << ":" << client->peerPort() << std::endl;
//this works fine
// while(client->waitForReadyRead()){
// receive_data();
// }
}
void Client::receive_data(){
QDataStream stream(client);
stream.setVersion(QDataStream::Qt_5_2);
quint32 magic; stream >> magic;
//interpret data
if(magic == GAMESERVER_MAGIC){
is_gameserver = true;
gameserver.Read(stream);
gameserver.port = client_port;
gameserver.ip = client_ip;
time(&(gameserver.last_update));
parent_server->add_server(gameserver.ip.toString(),gameserver);
std::cout << "GameServer " << gameserver.name << " registerd" << std::endl;
}else if(magic == CLIENT_MAGIC){
is_gameserver = false;
clientdata.Read(stream);
//get nearby servers
GameServerListPacket server_list = parent_server->getServerList(clientdata);
QDataStream outstream(client);
server_list.Write(outstream);
std::cout << "Sending ServerList(" << server_list.server_count << ") to " << client->peerAddress().toString().toStdString() << std::endl;
if(auto_disconnect){
//client->flush();
client->waitForBytesWritten();
}
}else{
std::cout << "Unknown package " << magic << std::endl;
}
//not enough data read, somthing is wrong, just for debugging
if(client->bytesAvailable()> 0) std::cout << "BytesAvailable " << client->bytesAvailable() << std::endl;
if(auto_disconnect) remove_from_clientlist();//close the connection once the serverlist was deployed
}
In the TcpServer.cpp add_client() is called when newConnection() was emitted by the QTcpServer:
void TcpServer::add_client(){
while(server->hasPendingConnections()){
QTcpSocket *socket = 0;
if(thread_pool.size() < max_connections && (socket = server->nextPendingConnection())){
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
client->run();
thread->start();
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
WRITELOCK(thread_pool.insert(client,thread));
}
}
}
the order calling client->run() and thread->start() doesn't seem to matter. Some time ago the code (not this exact code) worked fine but I can't remember what I changed that made it fail. Any help is appreciated!
Thanks in advance
Fabian
Edit 1:
I derived from QTcpServer and reimplemented void incomingConnection(qintptr socketDescriptor) which works fine. I dont use QThreadPool, its just a QMap and remove_client(Client*) closes the QTcpSocket and stops the thread and removes it from the map. Everything works fine on linux, on windows I get the following error: QSocketNotifier: socket notifiers cannot be disabled from another thread ASSERT failure in QCoreApplication::sendEvent: "Cannot send events to objects owned by a different thread....
Caused by this remove_client(Client*)
void TcpServer::remove_client(Client *client){
//disconnect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
lock.lockForWrite();
QMap<Client*,QThread*>::iterator itr = thread_pool.find(client);
if(itr != thread_pool.end()){
//delete itr.key(); causes the problem on windows
itr.value()->quit();
itr.value()->wait();
delete itr.value();
thread_pool.erase(itr);
}
lock.unlock();
}
Where and how should I free the Client object? If i'd use QThreadPool theres no way to iterate through the clients in case i want to send a message to more than one client. I could use a list/map holding only the Client* but then QThreadPool might delete them for me right before i want to access it. Any suggestions?
There is a problem with how you move your client object to a new thread. Actually, Client::run executes in the same thread as TcpServer::add_client.
Also QTcpSocket client remains in the default thread, while its container (Client class) is moved to a new thread. That's why the connection with Qt::DirectConnection type doesn't work.
Try this:
class Client : public QObject
{
Q_OBJECT
...
public slots:
void run();
...
}
Client::Client(int _socket, TcpServer *parent,bool _auto_disconnect)
{
...
client = new QTcpSocket(this);
}
void Client::run()
{
...
connect(client, SIGNAL(readyRead()), this, SLOT(receive_data()));
...
}
And here's how you should move your client to a new thread:
void TcpServer::add_client()
{
...
QThread *thread = new QThread();
Client * client = new Client(socket->socketDescriptor(),this,auto_disconnect);
client->moveToThread(thread);
connect(thread, SIGNAL(started()), client, SLOT(run()));
thread->start();
...
}
There are a number of things wrong with your code.
1.You have two QTcpSocket object trying to collect data from the same underlying socket descriptor. You appear to use the first one only to get access to the socket descriptor value which you then pass to your Client class. You might end up losing data because you won't be able to tell which socket will be getting what data from the operating system.
If you are creating a derived class of QTcpServer, rather reimplement QTcpServer::incomingConnection(qintptr socketDescriptor) instead of your existing TcpServer::add_client() function. Since this protected function is called once for every new connection, you don't need to make any connections to the newConnection() signal, nor do you have to loop while new connections are pending. You will also then only have one QTcpSocket connected to each socket descriptor so you won't lose data.
2.You seem to be using QThreadPool to manage threads. If you make Client a derived class of QRunnable (take not that with multiple inheritance of QObject, QObject must always be first), you don't need to check the maximum connections and you can eliminate all the QThread boiler-plating.
Taking 1. and 2. into account, your TcpServer::add_client() function will be replaced with:
void TcpServer::incomingConnection(qintptr socketDescriptor){
Client * client = new Client(socketDescriptor,this,auto_disconnect);
connect(client,SIGNAL(disconnected(Client*)),this,SLOT(remove_client(Client*)));
QThreadPool::globalInstance()->start(client);
}
With QThreadPool, there's no need to check whether the max number of threads has been reached or not. If the maximum has been reached, any new calls to start() will queue the next connection until a thread becomes available.
3.The reason your socket is not reading any data unless you call waitForReadyRead() is because you're executing the run() function in the main thread, creating the local socket in the main thread, you make a DirectConnection with the instance of Client and then move client to a different thread. You cannot have direct connections between threads.
You will need to add a local QEventLoop to your run() function to handle all events and signals of your new thread but remember to connect signals to your loop's quit() slot so the run() function will exit, otherwise your thread will continue to run forever.