4

I am working with Qt websockets.

Wanted to ask you, do you know how could I make this communication:

for example I have this two methods and I would like to send message to server, than wait for response (because it refreshes the data variable) and than proccess myMethod()

client->sendMessageToServer();
myMethod(data);

Sure I could use Signal and Slots... but dont know how could I use it here, see:

when I go sendMessageToServer() ok it will send message to server

void Client::sendMessageToServer(QString &str){

     m_wSocket.sendTextMessage(str);  
}

what should I emit than? I have no idea how to be in waiting state... there is no such a slot in QWebSocket, it just go to method myMethod immediately. It doesn't go here where the data are set: btw I have setup client like this when it recieves message it goes to onTextMessageRecieved because of this:

connect(&m_wSocket, &QWebSocket::textMessageReceived, this, &Client::onTextMessageReceived);

void Client::onTextMessageReceived(QString message)
{
    setData(message);       
}

Do you have any idea?

Hayt
  • 5,210
  • 30
  • 37
Dušan Tichý
  • 498
  • 1
  • 7
  • 21
  • you mean signals like `textMessageReceived` ? connect your method you want to call to those. And call your `myMethod` in the handler for this. – Hayt Oct 28 '16 at 10:46
  • You also can emit a custom signal in `setData` and connect this signal with `myMethod` – Hayt Oct 28 '16 at 10:48
  • problem is,it doesnt reach onMessageRecieved so neiter setData... its connected properly, just in using code with 2 methods sendMessageToserver and mymethod, myMethod doesnt have its data actualised. – Dušan Tichý Oct 28 '16 at 10:50
  • when `onMessageRecieved` will not be called you don't receive any data and something else is wrong somewhere. – Hayt Oct 28 '16 at 10:51
  • I recieve data but after myMethod is called... its just its not synchronized or something... It just skip that recieving because its slower or something... – Dušan Tichý Oct 28 '16 at 10:53
  • 1
    See also [this question](http://stackoverflow.com/q/32486198/1329652). – Kuba hasn't forgotten Monica Oct 28 '16 at 14:21

3 Answers3

3

You can emit a signal on setData or onTextMessageReceived and connect to this.

void Client::setData(QString message)
{
    //... whatever you do in setData

    emit dataChanged();       
}

in the other class you then can do

connect(client, &Client::dataChanged,this,&<...>::myMethod);

then just call

client->sendMessageToServer();
//without the myMethod call

And whenever setData will be called myMethod will automatically be called too.

Qt is not meant to be "waiting" most of the times. It is event driven. You define an event (or use one already existing) and tell the program what to do when this event happens.

It is a bit unusual compared to "normal" programming but you get used to it.

Hayt
  • 5,210
  • 30
  • 37
1

I have implemented an example that works like that for a problem I'm solving. In this problem, I have to acquire images from a camera that requires a websocket connection. Then, to make the code simpler, I'm using lambda functions for the callbacks and a special trick I've learned somewhere that is creating an event loop and waiting for a signal to happen before it quits. It is pretty useful when you don't wanna deal with asynchronous calls.

Here is the code:

QJsonObject Schedule::getImageWithInfo()
{
    QString response;
    QString* responsePtr = &response;

    QWebSocket websocket;
    QWebSocket* websocketPtr = &websocket;

    QObject::connect(websocketPtr, &QWebSocket::connected, [&, websocketPtr, responsePtr]()
    {
        qInfo() << "Schedule::getImageWithInfo: Connected";
        QObject::connect(websocketPtr, &QWebSocket::textMessageReceived, [websocketPtr, responsePtr](const QString& msg)
        {
            qInfo() << "Schedule::getImageWithInfo: message received";
            *responsePtr = msg;
            websocketPtr->close();
        });

        QJsonObject command;
        command.insert("command", "GET_IMAGES_WITH_INFO");
        QJsonDocument doc(command);
        QString strJson(doc.toJson(QJsonDocument::Compact));
        qInfo() << "Schedule::getImageWithInfo: Sending command " << strJson;

        websocketPtr->sendTextMessage(strJson);
    });

    websocket.open(QUrl(urlStr));

    QEventLoop eventLoop;
    QObject::connect(&websocket, SIGNAL(disconnected()), &eventLoop, SLOT(quit()));
    eventLoop.exec();

    QJsonObject responseObj = Utils::QJsonObjectFromString(response);
    return responseObj;
}
Fernando
  • 1,477
  • 2
  • 14
  • 33
  • A local QEventLoop is the right way to go. I think that you should register the `disconnected` signal before calling open – Kiruahxh Apr 19 '23 at 07:11
0

Well the truth is it worked like this:

FIRST it processed myMethod() and than it reached onMessageRecieved, which was too late. to what I ve done is I removed mymethod() a put it into a slot. I made it emit whenever message has come.

Dušan Tichý
  • 498
  • 1
  • 7
  • 21