Как узнать, какой QTcpSocket выдал сигнал readyRead()?

Я создал программу приветствия, чтобы понять, как работают QTcpServer и QTcpSocket. В нем QTcpServer принимает новые соединения и соединяет их сигнал readyRead() со слотом MainWindow::onNewData(), где их новые данные добавляются к текстовому элементу управления.

Проблема в том, что несколько сокетов могут быть открыты одновременно. Итак, когда я получаю сигнал readyRead() и хочу прочитать данные с помощью readAll(), как мне узнать, какой сокет его испустил?

Вот соответствующие части кода. Я вообще не храню здесь указатели QTcpSocket, но даже если бы и хранил, то все равно не знал бы, какой из них излучает сигнал.

    // 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());
}

person sashoalm    schedule 08.07.2012    source источник


Ответы (2)


Лучший способ (как мне кажется) - реализовать свой собственный класс Client, который будет инкапсулировать 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;
};

Самый простой способ: используйте QObject::sender() в функции слота

person pure cuteness    schedule 08.07.2012
comment
Спасибо, я использовал QObject::sender(). - person sashoalm; 09.07.2012
comment
Существует довольно старый пример от Trolltech, в котором используется QTcpSocket* socket = (QTcpSocket*)sender(); но я не смог найти этот подход в более новых примерах. Есть ли недостатки/проблемы с этим подходом? - person scai; 09.07.2012
comment
Недостатков нет, за исключением того, что вы никогда не должны использовать приведения типов C в коде C++! Правильно это сделано как QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender()); if (socket == 0) return; - person Kuba hasn't forgotten Monica; 09.07.2012

Используя лямбда-функции С++ 11 в операторе подключения, это также можно сделать без функции sender():

connect(socket, &QIODevice::readyRead,
        [this, socket()] { readData(socket) });

и функция сопоставления (которая не обязательно должна быть, но может быть слотом):

void foo::readData(QTcpSocket *socket)
{
    socket->whatever();
}
person Tobias Leupold    schedule 05.09.2018