I'm new in QT5 and decided to create simple multithreaded tcp server. I've read examples provided in QT but they have additional functions and complexity which I'm trying to avoid at this point. Here is my code:
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QTcpServer>
#include <QTcpSocket>
#include "threadz.h"
class Server : public QTcpServer
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
signals:
public slots:
void newConnection();
private:
QTcpServer *serv;
};
#endif // SERVER_H
threadz.h
#ifndef THREADZ_H
#define THREADZ_H
#include <QThread>
#include <QDebug>
#include "server.h"
class Threadz : public QThread
{
Q_OBJECT
public:
explicit Threadz(QObject *parent = 0);
void run(QTcpServer *serv);
signals:
public slots:
};
#endif // THREADZ_H
server.cpp
#include "server.h"
Server::Server(QObject *parent) :
QTcpServer(parent)
{
serv = new QTcpServer(this);
connect(serv, SIGNAL(newConnection()), this, SLOT(newConnection()));
if(!serv->listen(QHostAddress::Any, 1234))
{
qDebug() << "Error";
}
}
void Server::newConnection()
{
Threadz *thred = new Threadz();
thred->start();
}
threadz.cpp
#include "threadz.h"
Threadz::Threadz(QObject *parent) :
QThread(parent)
{
}
void Threadz::run(QTcpServer *serv)
{
QTcpSocket *socket = serv->nextPendingConnection();
socket->write("Hello!r\n");
socket->waitForBytesWritten();
socket->close();
}
main.cpp
#include <QCoreApplication>
#include "simplehttp.h"
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server gio;
return a.exec();
}
Basically, Im trying to create new thread for every client that connects server. But problem is that when I run this code and connect server with telnet 127.0.0.1 1234 nothing is printed on the screen. No errors but nothing is printed neither. Im using ubuntu 14.04. Sorry if question is silly and thanks in advance.
The QThread::run function is not implemented.
void QThread::run() [virtual protected]
The starting point for the thread. After calling start(), the newly created thread calls this function. The default implementation simply calls exec().
You can reimplement this function to facilitate advanced thread management. Returning from this method will end the execution of the thread.
Instead you implemented void Threadz::run(QTcpServer *serv) but something needs to call this function.
Related
I'm trying to fetch some data from an API using QNetworkRequest following this video (https://youtu.be/G06jT3X3H9E)
I have a RoR server running on localhost:3000 and I'm trying to fetch something from it.
.h file:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QAuthenticator>
#include <QNetworkProxy>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
signals:
public slots:
void get(QString code);
private slots:
void readyRead();
void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator);
void encrypted(QNetworkReply *reply);
void finished(QNetworkReply *reply);
void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
void preSharedKeyAuthenticationRequired(QNetworkReply *reply, QSslPreSharedKeyAuthenticator *authenticator);
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
private:
QNetworkAccessManager manager;
};
#endif // WORKER_H
.cpp file:
void Worker::get(QString code)
{
qInfo() << "Getting something from the server...";
QNetworkReply* reply = manager.get(QNetworkRequest(QUrl(QString("http://localhost:3000/api/v1/circle_gift_cards/scan?codes=" + code))));
connect(reply, &QNetworkReply::readyRead, this, &Worker::readyRead);
}
void Worker::readyRead()
{
qInfo() << "ReadReady";
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
if(reply) qInfo() << reply->readAll();
}
The result from:
Worker worker;
worker.get("abc");
is: "Getting something from the server..."
it should print "ReadReady" when the request is ready, but I don't think the request is being made, there's nothing in the console either.
[Edit 1]
What is calling the worker is this
void MainWindow::on_lineEditScanCard_textChanged(QString code) {
Worker worker(this->site);
worker.get(code);
}
It's an Edit field(where the user is supposed to type a code
[Edit 2]
I removed all app code and did this:
#include <QApplication>
#include "Forms/mainwindow.h"
#include "Requests/worker.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Worker worker;
worker.get("abc");
return a.exec();
}
And it worked... Why it does not work when called when the Edit text is changed?
Remember the concepts of scope, life cycle, and local variables? In your case worker is a local variable that will be destroyed instantly so the slot is not invoked, use
Worker * worker = new Worker;
worker->get("abc"); //remember to delete the memory when you no longer use it
I am trying to send signal across threads.
For testing this situation, I wrote a test code.
I am working on ubuntu 16.04 machine and qt version is 4.8.
In my code, three class exists:
1 - timer_class -> in this class, I emit signal in timeout slot.
2 - test_worker -> I am using this class as thread's worker.
3 - main_class -> I create timer_class instance, and also create thread in this class constructor.
I am trying to connect timer_class signal to test_worker slot.
Here is my code:
First; timer_class :
Header File:
#ifndef TIMER_CLASS_H
#define TIMER_CLASS_H
#include <QTimer>
#include <QDebug>
#include <QObject>
class timer_class : public QObject
{
Q_OBJECT
public:
timer_class(QObject *parent = 0);
~timer_class();
void start_timer();
signals:
void dummy_signal();
private slots:
void on_timeout_occur();
private:
QTimer *timer;
};
#endif // TIMER_CLASS_H
Source File :
#include "timer_class.h"
timer_class::timer_class(QObject *parent)
:QObject(parent)
{
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(on_timeout_occur()));
}
timer_class::~timer_class()
{
}
void timer_class::start_timer()
{
timer->start(1000);
}
void timer_class::on_timeout_occur()
{
qDebug() << "timeout occur";
emit dummy_signal();
}
Second, thread_worker class :
Header File :
#ifndef THREAD_WORKER_H
#define THREAD_WORKER_H
#include <QDebug>
#include <QObject>
class thread_worker : public QObject
{
Q_OBJECT
public:
thread_worker(QObject *parent = 0);
~thread_worker();
public slots:
void main_loop();
void on_dummy_signal();
};
#endif // THREAD_WORKER_H
Source File :
#include "thread_worker.h"
thread_worker::thread_worker(QObject *parent)
:QObject(parent)
{
}
thread_worker::~thread_worker()
{
}
void thread_worker::main_loop()
{
forever
{
//qDebug() << "In Main Loop";
}
}
void thread_worker::on_dummy_signal()
{
qDebug() << "dummy signal received";
}
And last, main_class :
Header file :
#ifndef MAIN_CLASS_H
#define MAIN_CLASS_H
#include <QObject>
#include <QDebug>
#include <QThread>
#include "timer_class.h"
#include "thread_worker.h"
class main_class : public QObject
{
Q_OBJECT
public:
main_class(QObject *parent = 0);
~main_class();
private:
QThread *thread;
timer_class *tmr_class;
thread_worker *worker;
};
#endif // MAIN_CLASS_H
Source File:
#include "main_class.h"
main_class::main_class(QObject *parent)
:QObject(parent)
{
tmr_class = new timer_class();
worker = new thread_worker();
thread = new QThread();
worker->moveToThread(thread);
connect(tmr_class, SIGNAL(dummy_signal()), worker, SLOT(on_dummy_signal()));
connect(thread, SIGNAL(started()), worker, SLOT(main_loop()));
thread->start();
tmr_class->start_timer();
}
main_class::~main_class()
{
}
In main.cpp, I just create main_class instance like this :
#include <QCoreApplication>
#include "main_class.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
main_class *main_cl = new main_class();
qDebug() << "executing a.exec";
return a.exec();
}
When I run the application, I saw "timeout occur" in console, but I don't saw "dummy signal received". I can not find problem.
Could you help me about this problem ?
Thanks.
The basic problem is that you're creating a new QThread, moving your timer_class instance onto that thread and then invoking thread_worker::main_loop when the thread starts. Since thread_worker::main_loop is basically a busy-waiting loop...
void thread_worker::main_loop ()
{
forever
{
//qDebug() << "In Main Loop";
}
}
...the QThread never gets a chance to process events thus preventing any signals being received via queued connections.
The correct fix for all of this depends to a large extent on what work (if any) you want thread_worker::main_loop to do.
To get things going in the mean time simply remove the forever loop or comment out the line...
connect(thread, SIGNAL(started()), worker, SLOT(main_loop()));
Having done that you should see the "dummy signal received" messages.
#include "dialog.h"
#include "ui_dialog.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QtWidgets>
#include <QString>
#include <string>
#include <QObject>
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
//ui->degree_lcdNumber->display("---");
// ui->distance_lcdNumber->display("---");
arduino_is_available = false;
port_name = "";
arduino =new QSerialPort;
serialBuffer = "";
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
if(serialPortInfo.hasVendorIdentifier() &&serialPortInfo.hasProductIdentifier()){
if(serialPortInfo.vendorIdentifier() == arduino_uno_vendorid){
if(serialPortInfo.productIdentifier()== arduino_uno_productid){
port_name = serialPortInfo.portName();
arduino_is_available = true;
}
}
}
}
if(arduino_is_available){
//open and configure the port
arduino->setPortName(port_name);
arduino->open(QSerialPort::ReadOnly);
arduino->setBaudRate(QSerialPort::Baud9600);
arduino->setDataBits(QSerialPort::Data8);
arduino->setParity(QSerialPort::NoParity);
arduino->setStopBits(QSerialPort::OneStop);
arduino->setFlowControl(QSerialPort::NoFlowControl);
QObject::connect(arduino,SIGNAL(readyRead()),this,SLOT(&serialReceived()));
}else{
//give error message
QMessageBox::warning(this,"Port Error","Couldn't find the Arduino!");
}
}
Dialog::~Dialog()
{
if(arduino->isOpen()){
arduino->close();
}
delete ui;
}
void Dialog::serialReceived(){
qDebug()<<"works" ;
QStringList bufferSplit = serialBuffer.split(".");
serialData = arduino->readAll();
serialBuffer += QString::fromStdString(serialData.toStdString());
serialBuffer = ",";
qDebug()<<bufferSplit;
}
void Dialog::updateLCD(const QString sensor_reading){
// ui->degree_lcdNumber->display(sensor_reading);
}
(.h)
#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include <QSerialPort>
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
private:
Ui::Dialog *ui;
QSerialPort *arduino;
static const quint16 arduino_uno_vendorid =9025;
static const quint16 arduino_uno_productid =67;
void updateLCD(const QString);
void serialReceived();
QString port_name;
//void readSerial();
QByteArray serialData;
QString serialBuffer;
bool arduino_is_available;
};
#endif // DIALOG_H
I just started the Qt. I want to connect Qt with arduino serially. I am reading the data but I am not able to connect with arduino slot.
I am getting a message after compilation. The message is QObject::connect: No such slot Dialog::&serialReceived() in ..\serial_sensor\dialog.cpp:45
QObject::connect: (receiver name: 'Dialog').
Can I know why?
As per the Qt Signals and Slot documentation, the Qt signals and slots have to be declared under signals: and public slots: respectively.
Why do we do that ?
Since slots are normal member functions, they follow the normal C++ rules when called directly. However, as slots, they can be invoked by any component, regardless of its access level, via a signal-slot connection. This means that a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class.( as per Qt Documentation)
class Dialog : public QDialog
{
Q_OBJECT
public:
explicit Dialog(QWidget *parent = 0);
~Dialog();
public slots :
void serialReceived();
signals :
// Declare Signals here.
private:
// other private declarations.
};
The reason your connection is failing is that your connect syntax is wrong. Either you have mixed Qt's functor and string based connections or accidentally added & in front of serialReceived. Below you can find two ways to do your connection. The first one is preferred. You can read more from here. Because Dialog is QObject based class you can just call connect.
Functor based connection:
connect(arduino, &QSerialPort::readyRead, this, &Dialog::serialReceived);
String based connection:
connect(arduino, SIGNAL(readyRead()), this, SLOT(serialReceived()));
If you are using Qt4 you have to use slots in your declaration. In Qt5 slots is not strictly required for connections but it should still be used. If you don't use it you can't use introspection. You can't e.g. call QMetaObject::invokeMethod. So, in short add slots to your header file as others have already suggested.
public slots:
void serialReceived();
I want to connect two threads. One Thread is the Mainthread of my application the other on is a workerthread. I have based my code on the following example doc.qt.io/qt-5/. For me it does not work completely. I am sending a QString to my WorkerThread (this works) and want to send it afterwards back to the MainThread (does not work). Before asking why I am doing this that's just a very simple example. The real Code is much more complex but I have exactly the same problem. If those example would run I am very sure that the complex one would work too. Here the code:
Main.cpp
#include "Controller_C.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller_C Controller;
Controller.SendData("Hello World!");
return a.exec();
}
Controller_C.cpp
#include "Controller_C.h"
#include <qmessagebox.h>
Controller_C::Controller_C(QWidget *parent)
: QMainWindow(parent),
Worker(new Worker_C())
{
ui.setupUi(this);
Worker->moveToThread(&WorkerThread);
connect(&WorkerThread, SIGNAL(started()), this, SLOT(ThreadStarted()));
connect(this, SIGNAL(SendToWorker(QString)), Worker, SLOT(DoWork(QString)));
connect(Worker, SIGNAL(SendToController()), this, SLOT(ReceiveData()));
WorkerThread.start();
}
Controller_C::~Controller_C()
{
}
void Controller_C::SendData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("We have send the following to the Worker Thread: %1").arg(aString));
emit SendToWorker(aString);
}
void Controller_C::ReceiveData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("The Controller received the following: %1").arg(aString));
}
Controller_C.h
#ifndef CONTROLLER_C_H
#define CONTROLLER_C_H
#include <QtWidgets/QMainWindow>
#include "ui_Controller_C.h"
#include "Worker_C.h"
#include <qthread.h>
class Controller_C : public QMainWindow
{
Q_OBJECT
public:
Controller_C(QWidget *parent = 0);
~Controller_C();
void SendData(QString aString);
private:
Ui::Qt_TestEnvironmentClass ui;
Worker_C* Worker;
QThread WorkerThread;
signals:
void SendToWorker(QString);
public slots:
void ReceiveData(QString aString);
};
#endif // CONTROLLER_C_H
Worker_C.cpp
#include "Worker_C.h"
#include <qmessagebox.h>
#include <qthread.h>
Worker_C::Worker_C()
{
}
Worker_C::~Worker_C()
{
}
void Worker_C::DoWork(QString aString)
{
QThread* Worker = QThread::currentThread();
emit SendToController(aString);
}
Worker_C.h
#ifndef WORKER_C_H
#define WORKER_C_H
#include <QObject>
class Worker_C : public QObject
{
Q_OBJECT
public:
Worker_C();
~Worker_C();
public slots:
void DoWork(QString aString);
signals:
void SendToController(QString);
};
#endif // WORKER_C_H
Thanks for your help.
Like the way you definied the Slot/Signal in your header:
void ReceiveData(QString aString);
void SendToController(QString);
You should also use them like this in your connect:
connect(Worker, SIGNAL(SendToController(QString)), this, SLOT(ReceiveData(QString)));`
I'm trying to create a TCP server in C++ with QT. I have the code but as soon as I try to connect to the server with SocketTest it says connection refused (most likely due to the server not running).
This is in my tcplistener.h:
#ifndef TCPLISTENER_H
#define TCPLISTENER_H
#include <QtNetwork/QTcpSocket>
#include <QtNetwork/QTcpServer>
class tcp_listener : public QTcpServer
{
Q_OBJECT
signals:
public slots:
void newConnectionFromServer()
{
QTcpSocket* newConnection = nextPendingConnection();
qDebug("New connection from %d", newConnection->peerAddress().toIPv4Address());
}
public:
tcp_listener(QObject *parent = 0)
: QTcpServer(parent)
{
listen(QHostAddress::Any, 30000);
connect(this, SIGNAL(newConnection()), SLOT(newConnectionFromServer()));
}
};
#endif // TCPLISTENER_H
This is in my engine.h:
#ifndef ENGINE_H
#define ENGINE_H
#include <QCoreApplication>
#include "tcplistener.h"
class engine
{
public:
void init()
{
qDebug("Initializing AuraEmu...");
tcp_listener list();
}
};
#endif // ENGINE_H
And this is my main.cpp:
#include <QCoreApplication>
#include "engine.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
engine eng = engine();
eng.init();
return a.exec();
}
Anybody know what the problem is?
The other answer, and my comment before that already cover what you did wrong, so I'll just supply the solution.
I've added comments because you said you come from Java and C#, but really, don't try to program C++ like it's Java or C#, because it's not.
class engine
{
public:
void init()
{
qDebug("Initializing AuraEmu...");
tcp_listener *list = new tcp_listener(); // Allocate on the heap instead of the stack.
}
~engine()
{
delete list; // C++ is an UNMANAGED language, there is no garbage collector
}
private:
tcp_listener *list; // This is a pointer to an object.
};
eng.init();
here you create
tcp_listener list();
and after eng.init() finished you detroy it, because
it is object on stack.