I just cannot get QTcpServer working (newConnection never called) - qt

I know similar question to this have been asked, but I haven't found an answer that fixes my problem.
I'm adapting some existing Qt code to add server functionality to a program my company uses. To that end I added a QTcpServer object to the existing dialog, call listen() and connect a slot to the newConnection emitter, like:
.h
class QConsole : public QDialog
{
Q_OBJECT
public:
void init();
public slots:
void new_Connection();
private:
QTcpServer m_Server;
}
.cpp
void QConsole::init()
{
m_Server.listen(QHostAddress::Any, 12346);
QDialog::connect(&m_Server, SIGNAL(newConnection()), this, SLOT(new_Connection()));
}
Main is:
int main( int argc, char *argv[] )
{
QApplication app(argc, argv);
QConsole * _output_window = new QConsole(desktopRect);
_output_window->init();
_output_window->show();
return app.exec();
}
new_Connection() never gets called so I can't see the relevance, but here it is:
void QConsole::new_Connection()
{
}
This works fine in that my program starts listening on the port specified and if I telnet to it a connection of sorts it made, but new_Connection() is never ever ever called!
I've seen posts on this problem dating back to 2005 so it's obviously not a new thing, but what I haven't found is a satisfactory answer to the problem (or any answer actually). This has got everyone at work stumped, even the person that has written a Qt server program. I'm guessing that there is something fundamentally wrong with the existing framework, but I have no idea what it might be.
I have been tearing my hair out for a day and a half over this, and the closes I got to success was using waitForNewConnection() which would actually return me a socket, but when I connected to the readReady() emitter, that was never fired either. So what would prevent these signals never getting called?
Please spare my sanity and help me as much as you can.

Here is a complete working example, tested using MSVC++ 2010.
This listens for a connection on port 12346, replies with "HELLO WORLD" and logs the connection to a list on the dialog.
main.cpp
#include <QtGui>
#include "console.hpp"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
Console con;
con.show();
return app.exec();
}
console.hpp
#include <QtCore>
#include <QtGui>
#include <QtNetwork>
class Console : public QDialog
{
Q_OBJECT
public:
Console();
public slots:
void connection();
private:
QTcpServer mServer;
QListWidget* mConnList;
};
console.cpp
#include "console.hpp"
Console::Console() :
QDialog(),
mServer(),
mConnList(new QListWidget())
{
if (!mServer.listen(QHostAddress::Any, 12346))
qDebug() << "Error during 'listen'" << mServer.errorString();
connect(&mServer, SIGNAL(newConnection()), this, SLOT(connection()));
QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->addWidget(mConnList);
setLayout(mainLayout);
}
void Console::connection()
{
qDebug() << "CONNECTION";
QTcpSocket* skt = mServer.nextPendingConnection();
if (!skt)
return;
mConnList->addItem(QString("%1:%2").arg(skt->peerAddress().toString()).arg(skt->peerPort()));
skt->write("HELLO WORLD!\r\n");
skt->close();
}
test.pro
TEMPLATE=app
CONFIG+=console debug
QT=core gui network
HEADERS=console.hpp
SOURCES=main.cpp console.cpp

Another working example, again on Linux, although I have coded a program using QTcpServer to run on both Linux and Windows before without a problem. If this doesn't work, surely it must be either a Qt installation or OS configuration problem. Either that or a bug in the Qt version.
~/tcp_test$ qmake --version
QMake version 2.01a
Using Qt version 4.8.6 in /usr/lib/x86_64-linux-gnu
~/tcp_test$ for file in qconsole.{h,cpp} main.cpp tcp_test.pro ; do echo -e "$file:\n"; cat $file; echo; echo; done
qconsole.h:
#include <QDialog>
#include <QTcpServer>
class QConsole : public QDialog
{
Q_OBJECT
public:
QConsole();
public slots:
void connection();
private:
QTcpServer server;
};
qconsole.cpp:
#include "qconsole.h"
QConsole::QConsole()
{
server.listen(QHostAddress::Any, 12346);
QDialog::connect(&server, SIGNAL(newConnection()), this, SLOT(connection()));
}
void QConsole::connection()
{
qDebug("got connection");
}
main.cpp:
#include <QApplication>
#include "qconsole.h"
int main( int argc, char *argv[] )
{
QApplication app(argc, argv);
QConsole * window = new QConsole();
window->show();
return app.exec();
}
tcp_test.pro:
QT = core gui network
CONFIG += debug
TARGET = tcp_test
SOURCES = main.cpp qconsole.cpp
HEADERS = qconsole.h
~/tcp_test$ ./tcp_test &
[3] 9784
~/tcp_test$ nc localhost 12346
got connection
^C

Related

In a Qt console application, why is a QTimer required for the code to exit properly?

I've wrote this code looking at examples online of how I'm supposed to run a console program that doesn't just run and quit and one that does. Based on a Qt console application. This one here, I wanted it to quit. I've understood pretty much everthing excepth the QTimer::singleShot line. If the line is commented out, the application will run but will not quit. If it is left, the application will run and quit as expected. Can anyone explain to me why?
dostuff.h
#ifndef DOSTUFF_H
#define DOSTUFF_H
#include <QObject>
#include <iostream>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0);
public slots:
void run();
signals:
void finished();
};
#endif // DOSTUFF_H
And the implementation dostuff.cpp
#include "dostuff.h"
DoStuff::DoStuff(QObject *parent):QObject(parent)
{
}
void DoStuff::run(){
for (int i = 0; i < 10000; i++){
std::cout << "Processing " << i << std::endl;
}
emit(finished());
}
My main.cpp
#include <QCoreApplication>
#include <QTimer>
#include "dostuff.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DoStuff *dostuff = new DoStuff(&a);
QObject::connect(dostuff,SIGNAL(finished()),&a,SLOT(quit()));
dostuff->run();
// WHY THIS??
QTimer::singleShot(10,dostuff,SLOT(run()));
return a.exec();
}
QTimer is not required to exit properly; You just need to provide a way to get your application to break the event loop at some point. In GUI application, Qt does that automatically when the last window is closed.
In Console applications, you can:
Either run your application without an event loop (if you have a straight-forward simple control flow in your application).
Or (if you require an event loop to handle some events or cross thread signal/slots) you need to have some event that makes your application break the event loop and quit. This event should only be triggered when the application has finished its job.
The code sample you have in your question is really simple, and does not require an event loop to run properly. The only effect the QTimer has in your code is that it delays execution for 10 ms. Here is the same code sample without running an event loop:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit);
dostuff.run();
return 0; //no event loop required
}
#include "main.moc"
If you start an event loop, you may notice that the quit slot does not work when not using QTimer::singleShot. The reason for this is that quit is called before the event loop is even started (and the call has no effect at all). That's why according to the docs, it is recommended to connect to quit using a queued connection:
It's good practice to always connect signals to this slot using a QueuedConnection. If a signal connected (non-queued) to this slot is emitted before control enters the main event loop (such as before "int main" calls exec()), the slot has no effect and the application never exits. Using a queued connection ensures that the slot will not be invoked until after control enters the main event loop.
So, if you want to have an event loop in your code above, you just need to connect using a Qt::QueuedConnection:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit,
Qt::QueuedConnection);
// ^^^^^^^^^^^^^^^^
// use a queued connection
dostuff.run();
return a.exec(); //start an event loop
}
#include "main.moc"
Timer is needed to postpone execution. Since you want to have a running event loop, a.exec() has to be called, then the timer executes your code. When your code finishes running, it triggers finished signal, that is tied to QCoreApplication::quit - that's the needed exit for event loop running inside a.exec().
Btw, you have to remove: dostuff->run(); from your code.

use QCamera in Qt console application

I want to use the camera in a headless (console) qt application (at least for unit testing).
But I facing a problem with Qt. As soon I use my code in a console application, the camera won't work - the readyForCaptureChanged event of QCameraImageCapture will not be called.
If I use exactly the same code in a gui application, the event gets triggered and I can capture images.
The common code I use is that:
camera = new QCamera(cameras.at(config->cameraNumber()));
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
// ——
void ImageCapture::readyForCapture(bool b) {
qDebug() << "ready for capture "<<b;
}
when I call this code in the gui application directly in the constructor of my MainWindow, it works (event will be triggered).
When I call this code in my qt console application, it does not work (event will not be triggered).
Can anybody help me? Thanks
** UPDATE 29. August - full code **
Console Application:
main.cpp
#include <QCoreApplication>
#include <QTest>
#include <QTimer>
#include <QDebug>
#include <runoneventloop.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
RunOnEventLoop * run = new RunOnEventLoop(&a);
QTimer::singleShot(0, run, SLOT(run()));
return a.exec();
}
RunOnEventLoop.cpp
#include "runoneventloop.h"
RunOnEventLoop::RunOnEventLoop(QObject *parent) :
QObject(parent)
{
}
void RunOnEventLoop::run() {
qDebug() << "hier run";
camera = new QCamera(0);
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
}
void RunOnEventLoop::readyForCapture(bool b) {
qDebug() << "ready of capture "<<b;
}
RunOnEventLoop.h
#ifndef RUNONEVENTLOOP_H
#define RUNONEVENTLOOP_H
#include <QObject>
#include <QDebug>
#include <QCamera>
#include <QCameraImageCapture>
class RunOnEventLoop : public QObject
{
Q_OBJECT
public:
explicit RunOnEventLoop(QObject *parent = 0);
private:
QCamera* camera;
QCameraImageCapture* imageCapture;
signals:
public slots:
void run();
void readyForCapture(bool);
};
#endif // RUNONEVENTLOOP_H
GUI Application
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug() << "hier";
camera = new QCamera(0);
imageCapture = new QCameraImageCapture(camera);
connect(imageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(readyForCapture(bool)));
camera->start(); // to start the viewfinder
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::readyForCapture(bool b) {
qDebug() << "ready of capture "<<b;
}
again, it's the same code. Console App does not call the readyForCapture method, while the gui application calls it.
you can download the archive here: DOWNLOAD
If would be nice if you could provide something more of your console-based Qt application... the code you presented, how is it called by your main code?
Anyway, just guessing, if no events are raised at all maybe it is because you are not running any event loop... are you sure that your code at some point call exec() on your QCoreApplication object? Are you sure that the owner of the object from which you call connect() is the thread of QCoreApplication?

Why is my mainwindow closing automatically when called from a differnet class?

I can't seem to figure out what went wrong so I'm here to ask you. I have made a simple class called BOBSNetworkSessionManager defined below. It is a simple class that inherits the QOBject so that I can use signals and slots but it does not have a dialog or any kind of window associated with it. It will eventually call a log in dialog and use the credentials to connect to a tcp server that I have created. This class serves as a layer to manage the connection state of the program because it will only run properly when connected to the server and when being used within 15 minutes without break due to p.c.i. compliance. If these conditions are not true this class will lock the window and force a new login. As of right now I just try to arbitrarily open the main window as though credentials had passed and i wasbconnected to the server. The problem is when I open the mainwindow it disapears right away. I cannot seem to figure out why it is diappearing. I have included all of my files.
BOBSDCNetworkSessionManager .h header file
#ifndef BOBSDCNETWORKSESSIONMANAGER_H
#define BOBSDCNETWORKSESSIONMANAGER_H
#include <QObject>
#include <QSettings>
class BOBSDCNetworkSessionManager : public QObject
{
Q_OBJECT
public:
explicit BOBSDCNetworkSessionManager(QObject *parent = 0);
protected:
void destroyed(QObject *);
signals:
public slots:
private:
void readSettings();
void writeSettings();
QSettings networkSettings;
};
#endif // BOBSDCNETWORKSESSIONMANAGER_H
BOBSDCNetworkSessionManager Implementation .cpp file
#include "bobsdcnetworksessionmanager.h"
#include "bobsmainwindow.h"
BOBSDCNetworkSessionManager::BOBSDCNetworkSessionManager(QObject *parent) :
QObject(parent)
{
BOBSMainWindow w;
w.show();
}
Main.cpp file
#include "bobsdcnetworksessionmanager.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
a.setApplicationName("Enterprise Management Suite");
a.setApplicationVersion("Beta Version: 0.0.0.01");
a.setOrganizationName("Enigma Web Consulting");
a.setOrganizationDomain("http://www.EnigmaWebCo.com");
BOBSDCNetworkSessionManager netMgr;
return a.exec();
}
The problem is here:
{
BOBSMainWindow w;
w.show();
}
w.show() is not a blocking call. So you're creating a window, showing it, and then it immediately is destructed when it goes out of scope. You should either declare w as a member variable or construct it on the heap:
BOBSMainWindow *w = new BOBSMainWindow(this);

Cannot read output using readyReadStandardOutput in Qt

I am using Qt and I am unable to get output of a exe file using readyReadStandardOutput.
Here is my code.
mainwindow.cpp
void MainWindow::on_pushButton_24_clicked()
{
myprocess = new QProcess(this);
myprocess->start("files\\helloworld.exe");
connect(myprocess, SIGNAL(readyReadStandardOutput ()), this, SLOT(outlog()));
}
void MainWindow::outlog()
{
QString abc;
abc = myprocess->readAllStandardOutput();
emit outlogtext(abc);
ui->lineEdit_4->setText(abc);
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QProcess *myprocess;
signals:
void outlogtext(QString ver);
private slots:
void outlog();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
The helloworld.exe will just give a output "Hello world" but I cannot see it in the textEdit, whats wrong with my code? I am very new to Qt. Thank you
I got the program working. Below is the code.
mainwindow.hpp
#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP
#include <QtGui>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void outlogtext(QString ver);
private slots:
void outlog();
void on_pushButton_24_clicked();
private:
QPushButton* pushButton_24;
QLineEdit* lineEdit_4;
QProcess *myprocess;
};
#endif // MAINWINDOW_HPP
main.cpp
#include <QtCore>
#include <QtGui>
#include <QDebug>
#include "mainwindow.hpp"
MainWindow::MainWindow(QWidget* parent)
: QMainWindow(parent)
{
pushButton_24 = new QPushButton;
connect(pushButton_24, SIGNAL(clicked()),
this, SLOT(on_pushButton_24_clicked()));
lineEdit_4 = new QLineEdit;
QWidget* central = new QWidget;
QLayout* layout = new QVBoxLayout();
layout->addWidget(pushButton_24);
layout->addWidget(lineEdit_4);
central->setLayout(layout);
setCentralWidget(central);
}
MainWindow::~MainWindow()
{
}
void MainWindow::on_pushButton_24_clicked()
{
myprocess = new QProcess(this);
connect(myprocess, SIGNAL(readyReadStandardOutput()),
this, SLOT(outlog()));
myprocess->start("./helloworld.exe");
// For debugging: Wait until the process has finished.
myprocess->waitForFinished();
qDebug() << "myprocess error code:" << myprocess->error();
}
void MainWindow::outlog()
{
QString abc = myprocess->readAllStandardOutput();
emit outlogtext(abc);
lineEdit_4->setText(abc);
}
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow win;
win.show();
return app.exec();
}
helloworld.cpp
#include <iostream>
int main()
{
std::cout << "Hello World!" << std::endl;
}
Some things I changed:
After constructing an object, I always connect signals and slots before performing the
actual operation on the object, which might be calling show() for widgets or calling
start() for threads. So I can be sure that I do not miss a signal like started(),
for example.
I ran the program on Linux. There I had to make sure that helloworld.exe was on my
path and I changed the command to ./helloworld.exe. I didn't create the sub-directory
called files as in your example.
The character to separate directories in Qt is the slash /. There are special functions to convert between the Qt-style and the native-style, when you want to display something to the user. Internally always make use of slashes. This even works for Windows programs (many console commands can cope with a slash instead of a backslash, too).
Adding debug output is really, really valuable during development. If the Makefile is
not set up correctly or something breaks, the helloworld.exe might end up in a directory, where it is not expected. Thus, I added code to wait for some time until the process has finished. This does not hurt because helloworld.exe needs just some milliseconds to run. Afterwards, I print the error code of QProcess just to be sure that the program has been found and could be executed. So I can be sure that the executable is on my path, that the executable flag is set, that I have permissions for executing the file etc.
I don't know exactly what causes the problem on your machine. However, comparing your solution to mine, having a look at the error code of QProcess and setting break points inside the slots should help you finding the error.

Qt QNetworkAccessManager does not emit signals

The function CheckSite() is called with an url like http://example.com, it initializes a QNetworkAccessManager object and connect() slots and signals.
The manger->get() call seems work (it generates http traffic) but does not call the slot replyFinished() at the request end.
What's wrong with this code?
#include <QtCore>
#include <QtNetwork>
class ClientHandler : public QObject
{
Q_OBJECT
QNetworkAccessManager *manager;
private slots:
void replyFinished(QNetworkReply *);
public:
void CheckSite(QString url);
};
void ClientHandler::replyFinished(QNetworkReply *reply) { qDebug() << "DONE"; }
void ClientHandler::CheckSite(QString url) {
QUrl qrl(url);
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(qrl));
}
Nothing. I wrapped it so it was fully functional and it works fine:
// placed in client.cpp
#include <QtDebug>
#include <QCoreApplication>
/* YOUR CODE */
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
ClientHandler handler;
handler.CheckSite("www.google.com");
return app.exec();
}
#include "client.moc"
It output "DONE" as expected. Maybe the site you're checking really isn't returning? Maybe it needs authentication or is producing ssl errors?
What code do you have around that? Do you spin an event loop somewhere? e.g. qapp.exec() ?

Resources