c++qtqt-signalsqtwebsockets

How to send a message from a client to a server using Qt WebSockets


I am using the webclient and webserver from the Qt examples

echoclient.cpp - https://pastebin.com/z8bgfQzE client main.cpp - https://pastebin.com/g1DtjjYa

echoserver.cpp - https://pastebin.com/V7aqHu2L server main.cpp - https://pastebin.com/Ni7CAXKu

And I have a simple Send SLOT:

void EchoClient::Send() {
    QTextStream qtin(stdin);
    QString word;
    qtin >> word;
    int sBytes = m_webSocket.sendTextMessage(word);
    std::cout << "Send bytes: " << sBytes << std::endl;
}

I want to enter data all the time, but I don't know what I can bind as a signal to trigger the slot:

connect(???, ???, this, &EchoClient::Send);

I tried overriding the Enter key press, but I couldn't do it in a Qt console application.


Solution

  • If you want the events from the main loop to be processed between each time a word is read, you need to make use of connections. This can be achieved with only 1 class but I suggest you limit the responsibilities of EchoClient so that it only does the communication. Something else will read from the input stream.

    Correct Send so that it only sends words it receives:

    void EchoClient::Send(const QString& word) {
        int sBytes = m_webSocket.sendTextMessage(word);
        std::cerr << "Send bytes: " << sBytes << std::endl;
    }
    

    Another class is in charge of reading from the input stream. We want it to read one 1, let the main loop process events, then be prepared to read the next word, and so on.
    It results very roughly in:

    class KeyboardReader : public QObject {
    Q_OBJECT
    public:
        KeyboardReader() {
            //Connection to make KeyboardReader::readWord loop upon itself by the event loop
            QObject::connect(this, &KeyboardReader::start, this, &KeyboardReader::readWord,
                             Qt::QueuedConnection | Qt::SingleShotConnection);
        }
    signals:
       void start();
       void wordReceived(const QString& word);
    public slots:
       void readWord();
    };
    
    void KeyboardReader::readWord() {
        QTextStream qtin(stdin);
        QString word;
        qtin >> word;
        emit wordReceived(word);
    }
    

    Then, the main function should look similar to:

    int main() {
        QCoreApplication a;
        EchoClient client;
        //Initialize/connect client here
    
        KeyboardReader reader;
        //Connection to make the message read by reader propagate to client
        QObject::connect(&reader, &KeyboardReader::wordReceived, &client, &EchoClient::Send);
        //Connection to make KeyboardReader::readWord loop upon itself in the Qt main loop
        QObject::connect(&reader, &KeyboardReader::wordReceived, &reader, &KeyboardReader::readWord);
        
        emit reader.start();
    
        return a.exec();
    }