Qt Getting Response from SoapRequest - c++

Consider the following in Qt using QtSoap lib:
QtSoapHttpTransport http;
http.setHost("XXXX",3333);
connect(&http, SIGNAL(responseReady()), this, SLOT(getResponse()));
now there is a method i want to call which is:
QtSoapMessage request;
request.setMethod("test");
request.addMethodArgument("xxx","zzzz",xxx);
request.addMethodArgument("xx","xx",xx);
http.submitRequest(Request, "/api/soap");
now i want to have something like this :
QString GetTest(){
while(http.isBusy); // no such a thing as isbusy
return http.getResponse().returnValue().toString();}
or any technique i can use to get the return value or wait for it and get it..
Thanks in advance...

I don't see a problem. The QtSoapHttpTransport reference already has a nice simple example.
If you want to have a getter that blocks and returns only when the response is received, doing active wait (your while loop) is absolutely not a way to go.
You already connect the responseReady signal to your slot, so the only missing thing would be to have a synchronization point that blocks your thread calling getTest until this slot is executed.
class Messenger : public QObject {
Q_OBJECT
public:
Messenger() { /* ... your initialization code with connect ... */ }
void sendRequest() { /* ... your sending code ... */ }
QString getTest() // call this from a worker thread to wait
{ // for a response to arrive and retrieve it
QMutexLocker lock(&responseMutex);
responseReady.wait(&responseMutex);
return http.getResponse().returnValue().toString();
}
public slots:
void getResponse() { // slot called by Qt event loop when response arrives
responseReady.wakeAll();
}
private:
QtSoapHttpTransport http;
QWaitCondition responseReady;
QMutex responseMutex;
};
Note that this design only makes sense if you have a multithreaded application and the thread calling getTest is a working thread, not event-driven thread.
On the other hand, if your application just wants to do something with the received response, there is imho no reason why you need a blocking method in the first place. Just perform your actions in the slot directly - just like it is in the Qt documentation.

Related

Signals and slots between objects in different threads in Qt

Basically, I've the next code:
class serverTCP : public QObject
{
// Other methods...
signals:
void newInstructions(QJsonDocument jDoc);
public slots:
void responseObtained(QJsonDocument jDoc);
}
class gatherModbus : public QObject
{
// Other methods...
signals:
void responseReady(QJsonDocument jDoc);
public slots:
void executeInstruction(QJsonDocument jDoc);
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
}
};
}
void main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
int netsNumber = 2; //In reality this is dynamic. It's only a example
serverTCP *server = new serverTCP;
gatherModbus * gather = new gatherModbus[netsNumber];
QThread * threads = new QThread[netsNumber];
// more necessary code...
for(int i = 0; i < netsNumber; i++)
{
gather[i].moveToThread(threads[i]);
QObject::connect(&server, SIGNAL(newInstructions(QJsonDocument)),
&gather[i], SLOT(executeInstruction(QJsonDocument)));
QObject::connect(&gather[i], SIGNAL(responseReady(QJsonDocument)),
&server, SLOT(responseObtained(QJsonDocument)));
QObject::connect(&threads[i], SIGNAL(start()),
&gather[i], SLOT(myprocess()));
// Other signals needed between the objects 'gather' and 'threads'
threads[i].start();
}
a.exec();
}
The problem is that the connections between objects 'server' and 'gather' do not work. The object 'server' is in the same thread as the 'main' function but objects 'gather' have moved to other threads.
What have I to do to make both objects can communicate properly?
My purpose is that the 'server' must be able to send a signal to all objects 'gather' there are. In each of the objects 'gather' must execute the slot and return the 'server' response if any.
If I set up the connection to be the type Qt::DirectConnection slots running on the same thread as the 'main' function and object 'server' and that does not interest me.
Any help or suggestions will be appreciated.
All is in Qt documentation.
First, read that.
Then if you're not satisfied, you can use QCoreApplication::postEvent() (for more informations you need : here)
Both signals/slots (QObject:connect()) and QCoreApplication::postEvent() are thread-safe and can solve your problem.
So events and signal/slots are two parallel mechanisms accomplishing the same things, in general an event will be generated by an outside entity (e.g. Keyboard, Mouswheel) and will be delivered through the event loop in QApplication. In general unless you set up the code you will not be generating events. You might filter them through QObject::installEventFilter() or handle events in subclassed object by overriding the appropriate functions.
Signals and Slots are much easier to generate and receive and you can connect any two QObject subclasses. They are handled through the Metaclass (have a look at your moc_classname.cpp file for more) but most of the interclass communication that you will produce will probably use signals and slots. Signals can get delivers immediately or deferred via a queue (if you are using threads) A signal can be generated
Your demo code seems OK. That's how we organize our current project. You'd better provide more detailed codes if necessary to explain your problem.
BTW, after reading your interests, I'd recommend you the QtConcurrent module which seems fitting your interest better.
Huh... Your code is not ok. This is the source of all your trouble
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
}
};
If you want the slots newInstructions and responseObtained slots to ever run, myprocess should not be an infinite loop. You need to :
Modify myprocess such that once it is done writing and reading currently available data, it completes
Have a mechanism to know that new processing need to be done. For instance, if you are using a QIODevice subclass (socket, input stream, etc...) you have the signal QIODevice::readyRead() which will notify you there is new data to read from the device. I suspect your newInstructions is supposed to do just that.
connect this mechanism to another call to myprocess to allow the processing to start again
Edit : Given your comment, this is a way to modify the infinite while loop without too much modification.
void myprocess() {
make_one_processing_round();
if(should_continue_processing())
{
QMetaObject::invokeMethod(this, &gatherModbus::myprocess, Qt::QueuedConnection);
}
};
QMetaObject::invokeMethod will schedule this method for execution at the back of the thread QEventLoop queue. Which means other slots can execute.
I can solve my problem adding the next line in the end of "myprocess" method:
QCoreApplication::processEvents(QEventLoop::AllEvents);
The final code of this method is this:
void myprocess() {
while(true)
{
// Write and read Serial Port
// Save data in json
// New line:
QCoreApplication::processEvents(QEventLoop::AllEvents);
}
};
With this line I get that events will processed if any. I don't known if it is the best solution, but it works as wanted.
Thanks to all of you for your help and answers.

how to use QTcpSocket in multithread?

in last question,i don't express my use-case clearly. now i describe my requirement.
in my client,i need to connect to Server with QTcpSocket.in most cases, i can write and read in gui thread(main thread).
how ever,in some time-consuming tasks,i need a single worker thread to execute task. when i connect the server in gui thread,i keep the connection all the time.
if i use a new QTcpSocket in worker thread,must i disconnect the socket in gui thread? and connect to Server again?
class Widget:public QWidget
{
Q_OBJECT
public:
Widget()
{
socket = new QTcpSocket(this);
}
private:
QHostAddress host;
unsigned int port;
QTcpSocket *socket;
private slots:
void startConnect()
{
socket->connectToHost(host,port);
}
void sendData()
{
//just send some bytes
//socket->write();
}
void doTimeConsumingTask()
{
//must i disconnect gui->socket connection before the Worker is running?
// socket->disconnectFromHost();
Worker * w = new Worker();
w->start();
}
}
class Worker:public QThread
{
Q_OBJECT
public:
Worker()
{
}
protected:
void run()
{
QTcpSocket socket;
// must i connectToHost again here ?
// do something consuming time
while(true){
//
QThread::msleep(10);
}
}
private:
QHostAddress host;
unsigned int port;
}
The easy solution to your problem is to not directly access the QTcpSocket from the worker thread. Ultimately, all you probably want to do with the socket from the worker thread is send and/or receive data to/from it. In that case, you can simply have the worker thread emit a signal with a QByteArray parameter, then connect that signal to a slot on the GUI thread that then calls write(const QByteArray& byteArray) on the QTcpSocket. Similarly, you can have your data receive function (whatever is connected to the readyRead() signal of the socket) either live in the worker thread, or live in your main thread, but upon receipt of data that the worker thread needs to process, pass it that data via a signal/slot connection.
The alternative, if you must directly access the socket (say, you need to do more than write to it, maybe you have to be able to close it or whatever), you need to wrap every use of that socket in a mutex, on both threads. This is probably best done by wrapping the raw QTcpSocket in another class that exposes only a few methods that you need, and always has a call like:
QMutexLocker locker(theMutex);
At the beginning of each function.
Is there a reason you can't pass the socket to the thread's constructor?
class Worker : public QThread{
public:
Worker(QTcpSocket* pSocket) : m_pSocket(pSocket) ...
Not sure of your use case but is there a reason you can't do this?
From the docs: http://doc.qt.io/qt-4.8/qiodevice.html
Certain subclasses of QIODevice, such as QTcpSocket and QProcess, are asynchronous. This means that I/O functions such as write() or read() always return immediately, while communication with the device itself may happen when control goes back to the event loop. QIODevice provides functions that allow you to force these operations to be performed immediately, while blocking the calling thread and without entering the event loop. This allows QIODevice subclasses to be used without an event loop, or in a separate thread:

Qt create a dialog that waits for a network event

I am writing the client for a client/server application. The clients are supposed to login using a login window. If the login is successful, a "waiting" window appears (this is just a window that contains a label). On the server side there is a barrier that waits for n clients to be logged in; when this happens, a message is broadcasted, the waiting window is supposed to close and a new window appears for every client.
The networking interface is implemented by me, using low-level functions, not the functionality provided by Qt.
The actual waiting loop is something like this:
char buffer[256];
while (strcmp(buffer, "proceed"))
read(sockfd, buffer, 256);
The problem is that if I start this loop in the main thread, the application blocks, for obvious reasons.
How can I make this loop run and not block the application, and close the dialog when it ends?
Later edit: I did also attempt to use QThreads, but, for reasons which I don't fully understand yet, the application still crashes:
class WaitLoop : public QThread {
public:
WaitLoop(NetworkHandler &network) : network(network) {}
private :
NetworkHandler &network;
void run() {
this->network.waitForGameStart();
}
};
In the wait dialog constructor:
WaitLoop *waitLoop = new WaitLoop(network);
connect(waitLoop, SIGNAL(finished()), this, SLOT(gameStartSlot()));
waitLoop->start();
The application still crashes using this approach.
The sanest way to approach this would not be using low-level functions, because you aren't writing in C. Use at least QAbstractSocket to wrap a sockfd. The setSocketDescriptor method lets you do it.
Your code then becomes non-blocking and asynchronous:
class Controller : public QObject {
Q_OBJECT
QStateMachine m_sm;
QState s_init{&m_sm}, s_proceeding{&m_sm};
QAbstractSocket m_socket;
Q_SIGNAL void proceed();
Q_SLOT void onData() {
auto data = m_socket.readAll();
if (data.contains("proceed")) proceed();
}
public:
Controller(QObject * parent = 0) : QObject(parent) {
connect(&m_socket, &QIODevice::readyRead, this, &Controller::onData);
s_init.addTransition(this, &Controller::proceed, &s_proceeding);
m_sm.setInitialState(&s_init);
m_sm.start();
}
bool setup(quintptr fd) {
return m_socket.setSocketDescriptor(fd);
}
};
Through the use of a state machine, it's easy to add more states, react to their transitions (see QState::onEntry signal, etc.), and ensure that the behavior is correct. Fleshing out a UML statechart forces you to think about handling corner cases, etc. See this answer for a full example.

Creating a custom message/event with Qt

I have an RPC thread that is calling back to me from that thread. I need to somehow inform Qt that it needs to make a function call from the main thread. In straight Windows I could do this by using a custom message and then posting that message to the message queue, e.g., I could create a WM_CALLFUNCTION message and pass the function pointer through wParam and the parameter (class pointer) through lParam.
Has anyone an idea how I could do this with Qt? I've come across QCustomEvent but I have no idea how to use it or how to process it. Any help would be hugely appreciated!
Edit:
In the end I went with QMetaObject::invokeMethod which works perfectly.
Using custom events generally involves creating your own QEvent subclass, overriding customEvent() in the QObject class that will receive the event (often the main window class) and some code that "posts" the event from your thread to the receiver.
I like to implement the event posting code as a method of the receiver class. That way, the caller only has to know about the recevier object and not any of the "Qt" specifics. The caller will invoke this method which will then essentially post a message to itself. Hopefully the code below will make it clearer.
// MainWindow.h
...
// Define your custom event identifier
const QEvent::Type MY_CUSTOM_EVENT = static_cast<QEvent::Type>(QEvent::User + 1);
// Define your custom event subclass
class MyCustomEvent : public QEvent
{
public:
MyCustomEvent(const int customData1, const int customData2):
QEvent(MY_CUSTOM_EVENT),
m_customData1(customData1),
m_customData2(customData2)
{
}
int getCustomData1() const
{
return m_customData1;
}
int getCustomData2() const
{
return m_customData2;
}
private:
int m_customData1;
int m_customData2;
};
public:
void postMyCustomEvent(const int customData1, const int customData2);
....
protected:
void customEvent(QEvent *event); // This overrides QObject::customEvent()
...
private:
void handleMyCustomEvent(const MyCustomEvent *event);
The customData1 and customData2 are there to demonstrate how you might pass some data along in your event. They don't have to be ints.
// MainWindow.cpp
...
void MainWindow::postMyCustomEvent(const int customData1, const int customData2)
{
// This method (postMyCustomEvent) can be called from any thread
QApplication::postEvent(this, new MyCustomEvent(customData1, customData2));
}
void MainWindow::customEvent(QEvent * event)
{
// When we get here, we've crossed the thread boundary and are now
// executing in the Qt object's thread
if(event->type() == MY_CUSTOM_EVENT)
{
handleMyCustomEvent(static_cast<MyCustomEvent *>(event));
}
// use more else ifs to handle other custom events
}
void MainWindow::handleMyCustomEvent(const MyCustomEvent *event)
{
// Now you can safely do something with your Qt objects.
// Access your custom data using event->getCustomData1() etc.
}
I hope I didn't leave anything out. With this in place, code in some other thread just needs to get a pointer to a MainWindow object (let's call it mainWindow) and call
mainWindow->postMyCustomEvent(1,2);
where, just for our example, 1 and 2 can be any integer data.
In Qt 3, the usual way to communicate
with the GUI thread from a non-GUI
thread was by posting a custom event
to a QObject in the GUI thread. In Qt
4, this still works and can be
generalized to the case where one
thread needs to communicate with any
other thread that has an event loop.
To ease programming, Qt 4 also allows
you to establish signal--slot
connections across threads. Behind the
scenes, these connections are
implemented using an event. If the
signal has any parameters, these are
also stored in the event. Like
previously, if the sender and receiver
live in the same thread, Qt makes a
direct function call.
--
http://doc.qt.nokia.com/qq/qq14-threading.html#signalslotconnectionsacrossthreads

Wait for a SLOT to finish

I use QNetworkAccessManager to do form POST.
I have connected signals and slots as:
connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(readCookies(QNetworkReply*)));
Now, I make a request by doing:
manager->post(request,postData);
Now readCookies(QNetworkReply *) will be run as soon as SIGNAL is emitted. Now, using the Cookies which I get in this slot, I have to make one more POST..
As signals & slots are asynchronous, I want to wait till I get the cookies from my first POST and then I again want to do another post using the cookies I got in first POST like
//Setting new request, headers etc...
manager->post(request2,postData2);
I want the later to always be executed after first one has executed (so that I get proper cookies value).
What is the way to go? I am new to all these SIGNALS & SLOTS so please bear with me.
You can do the post in your readCookies() slot:
void readCookies( QNetworkReply* reply ) {
if ( ...error? ) {
report error...
return;
}
...
manager->post(request2,postData2);
}
I will be called when the cookies is read, and you can then continue with your post. Connect that to a second slot, and so on.
Managing multiple, possibly parallely running asynchronous operations like this can become errorprone though, if you manage many of them in a single object. I would suggest to use the Command Pattern - here I described why I find it extremely useful in exactly this context. The sequence of request and asnychronous operations is encapsulated in a single object (abbreviated, with some pseudo-code):
class PostStuffOperation : public QObject {
Q_OBJECT
public:
enum Error {
NoError=0,
Error=1,
...
};
Error error() const; //operation successful or not?
QString errorString() const; //human-readable error description
... setters for all the information the operation needs
...
void start() {
...start your first request and connect it to cookiesRead
}
public Q_SLOTS:
void cookiesRead( QNetworkReply * ) {
if ( error ) {
// set error and errorString...
emit finished( this ); //couldn't read cookies, so the operation fails
return;
}
... do post
}
void postFinished( QNetworkReply* ) {
if ( error ) {
// set error and errorString...
}
emit finished( this ); //post finished - that means the whole operation finished
}
Q_SIGNALS:
void finished( PostStuffOperation* );
};
To start the operation, you do
PostStuffOperation op* = new PostStuffOperation( this );
... pass data like server, port etc. to the operation
connect( op, SIGNAL(finished()), this, SLOT(postOperationFinished()) );
op->start();
void postOperationFinished( PostStuffOperation* op ) {
if ( op->error != PostStuffOperation::NoError ) {
//handle error, e.g. show message box
}
}
It makes sense to have a common baseclass for such operations, see e.g. KDE's KJob.
You can connect a signal from this to a slot from your manager and emit the signal after reading the cookies. By example:
connect(this, SIGNAL(cookiesRead()), manager, SLOT(PostAgain());
So your readCookies function will be:
{
// Read cookies
emit cookiesRead();
}
Of course you can send all data you want form signal to slot.
Hope that helps
You can send a second signal connected to another slot (the resend slot), if you have finished the evaluation of your first cookie. You can do that directly in the slot. You can also call slots like a normal member function.