How do I know which QTcpSocket emitted the readyRead() signal?
-
19-06-2021 - |
Question
I've created a hello-world program to help me understand how QTcpServer and QTcpSocket work. In it the QTcpServer accepts new connections and connects their readyRead()
signal to the MainWindow::onNewData()
slot where their new data is appended to a plain text control.
The problem is that multiple sockets can be opened simultaneously. So when I get the readyRead()
signal and I want to read the data with readAll()
, how do I know which socket emitted it?
Here's the relevant parts of the code. I'm not storing the QTcpSocket pointers at all here, but even if I did, I still wouldn't know which one of them emitted the signal.
// constructor
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
server->listen(QHostAddress::LocalHost, 3333);
void MainWindow::onNewConnection()
{
QTcpSocket* socket = server->nextPendingConnection();
connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
connect(socket, SIGNAL(readyRead()), this, SLOT(onNewData()));
}
void MainWindow::onNewData()
{
ui->plainTextEdit->appendPlainText(WHICH_SOCKET_EMITTED_IT()->readAll());
}
Solution
The best way (as it seems to me) is to implement your own Client
class which will encapsulate QTcpSocket
class Client : public QObject
{
Q_OBJECT
public:
Client(QTcpSocket *socket)
: m_socket(socket)
{
connect(socket, SIGNAL(readyRead()), this, SLOT(onNewData()));
}
private slots:
void onNewData();
private:
QTcpSocket *m_socket;
};
Easiest way: use QObject::sender()
in slot function
OTHER TIPS
Using a C++11 lambda functions in the connect statement, it's also possible to do this without the sender()
function:
connect(socket, &QIODevice::readyRead,
[this, socket()] { readData(socket) });
and a matching function (which does not need to be but can be a slot):
void foo::readData(QTcpSocket *socket)
{
socket->whatever();
}