Get SO_RCVBUF socket option value from Qt - qt

I want to get the value of the SO_RCVBUF socket option used by Qt to be sure that it uses by default the system value (that I changed).
But the following piece of code returns an "Invalid" QVariant:
QUdpSocket socket;
qDebug() << socket.socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
Does it mean that the socketOption() Qt method only get the value if it has been set with setSocketOption()?
Or did I make a mistake?

In order to obtain the socket information, then the native socket must have been created, that is, obtain a socketDescriptor() other than -1, but in your case it is not connected causing that value not to be read, returning a invalid QVariant.
The solution is to connect the socket and analyze that the socket is valid to obtain the desired information:
#include <QCoreApplication>
#include <QTimer>
#include <QUdpSocket>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QUdpSocket socket;
QObject::connect(&socket, &QAbstractSocket::stateChanged, [&socket](){
if(socket.socketDescriptor() != -1){
qDebug() << socket.socketOption(QAbstractSocket::ReceiveBufferSizeSocketOption);
// kill application
QTimer::singleShot(1000, &QCoreApplication::quit);
}
});
socket.bind(QHostAddress::LocalHost, 1234);
return a.exec();
}
Output:
QVariant(int, 212992)

Related

Registring QList<CustomType>

I got a runtime crash when registering a QList (CustomType is a Q_GADGET generate by the repc (Qt remote object compiler)).
Actually I am trying to expose a list of custom type using Qt Remote Object.
file.rep :
POD Service(QString name, QUrl enpoint)
POD Services(QList<Service> svcs)
class ROObject
{
PROP(bool state = false);
PROP(Services services);
}
main.cpp:
#include <QCoreApplication>
#include <QTimer>
#include <QRemoteObjectHost>
#include "rotest.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qRegisterMetaType<QList<Service>>();
ROTest t;
QList<Service> l;
l.push_back(Service("houssem", QUrl("local:houssem")));
l.push_back(Service("houss", QUrl("local:houss")));
Services ss(l);
t.setServices(ss);
QRemoteObjectHost host;
host.setHostUrl(QUrl("local:s"));
host.enableRemoting(&t);
qDebug() << "Services : " << t.services().svcs().count();
return a.exec();
}
error:
Thank you for your help.
Qt doesn't know how to serialize your custom types.
In addition to registering it as a meta type, you need to implement and register stream operators for it:
void qRegisterMetaTypeStreamOperators(const char *typeName)
Registers the stream operators for the type T called typeName.
Afterward, the type can be streamed using QMetaType::load() and
QMetaType::save(). These functions are used when streaming a QVariant.
qRegisterMetaTypeStreamOperators<MyClass>("MyClass");
// The stream operators should have the following signatures:
QDataStream &operator<<(QDataStream &out, const MyClass &myObj);
QDataStream &operator>>(QDataStream &in, MyClass &myObj);
Also, what you actually need to register as a meta type is Service and not QList<Service>. Once service is registered and its streaming operators are implemented you should be all set, Qt knows how to handle the QList part.

QNetworkAccessManager is not sending data part of POST request

When sending POST data to server, from Qt application looks everything good but data part of HTTP part were not sent. In Wireshark in POST packet is visible correct "Content-Length" value but size of whole HTTP segment is only about 226 bytes (is independent on POST data size).
I can't find reason why data part is not send. Any idea?
The application is running in console. A complete source is below.
project.pro:
QT += widgets
QT -= gui
QT += network
CONFIG += c++11
TARGET = POSTrequest
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
main.cpp:
#include <QObject>
#include <QApplication>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QNetworkRequest request(QUrl("http://www.server.com/index.php"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkAccessManager manager;
QNetworkReply *reply = manager.post(request, "a=aaaaaa");
QObject::connect(reply, SIGNAL(finished()), &a, SLOT(quit()));
return a.exec();
}
This works for me on both OS X and Windows:
#post-request-36549732.pro
QT = core network
CONFIG += console c++11
CONFIG -= app_bundle
TARGET = post-request-36549732
TEMPLATE = app
SOURCES += main.cpp
// main.cpp
#include <QtNetwork>
int main(int argc, char ** argv)
{
QCoreApplication a{argc, argv};
QNetworkAccessManager manager;
QByteArray post{"a="};
post.append(QByteArray{512, 'b'});
QNetworkRequest req(QUrl("http://server/test.php"));
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
// Must be a queued connection, or else the multi-threaded manager might
// win the race and signal quit before `a.exec()` starts running. In such
// case, the `quit()` is a NOP. We don't want that.
QObject::connect(&manager, &QNetworkAccessManager::finished, &a, [](QNetworkReply * reply){
qDebug() << reply->errorString();
qApp->quit();
}, Qt::QueuedConnection);
manager.post(req, post);
return a.exec();
}
You might be interpreting your Wireshark data incorrectly. Make sure you're looking at the Reassembled TCP aspect of the HTTP request. Here's how it looks for me; server is 192.168.2.1:

Qt connect - object emits signal before connect is issued

I have following main.cpp:
#include <QtQml>
#include <QApplication>
#include <QQmlApplicationEngine>
#include "database/uepeoplemodel.h"
#include "core/uestatus.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
UeStatus* ueApplicationStatus=new UeStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
QObject::connect(uePeopleModel,
SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
ueApplicationStatus,
SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));
engine.rootContext()->setContextProperty("uePeopleModel",
uePeopleModel);
engine.rootContext()->setContextProperty("ueApplicationStatus",
ueApplicationStatus);
engine.addImageProvider(QLatin1String("uePeopleModel"),
uePeopleModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Now, inside main.cpp I create two objects from classes:
UeStatus* ueApplicationStatus=new UeStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
and I connect signal from UePeopleModel to slot in ueApplicationStatus:
QObject::connect(uePeopleModel,
SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
ueApplicationStatus,
SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));
The problem is when uePeopleModel is created, the signal is emmited inside constructor:
UePeopleModel::UePeopleModel(QObject* parent)
: QSqlQueryModel(parent),
QQuickImageProvider(QQmlImageProviderBase::Image,
QQmlImageProviderBase::ForceAsynchronousImageLoading)
{
if(!QSqlDatabase::connectionNames().contains(UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE,
Qt::CaseInsensitive))
{
this->ueSetDatabase(QSqlDatabase::addDatabase(UePosDatabase::DATABASE_DRIVER,
UePosDatabase::UeDatabaseConnectionNames::DATABASE_CONNECTION_NAME_PEOPLE));
} // if
this->ueDatabase().setHostName(/*this->uePosSettings()->ueDbHostname()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_HOSTNAME);
this->ueDatabase().setDatabaseName(/*this->uePosSettings()->ueDbName()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_NAME);
this->ueDatabase().setUserName(/*this->uePosSettings()->ueDbUser()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_USERNAME);
this->ueDatabase().setPassword(/*this->uePosSettings()->ueDbPassword()*/UePosDatabase::UeDatabaseConnectionParameters::DATABASE_PASSWORD);
if(this->ueDatabase().open())
{
emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
this->ueDatabase());
/*
if(this->lastError().isValid())
qDebug() << this->lastError();
*/
}
else
{
emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
// qDebug() << this->ueDatabase().lastError();
}
// qDebug() << this->ueDatabase().connectionNames();
} // default constructor
before connect is issued and therfore ueApplicationStatus object does not catch is with slot. Does anyone has idea how to get rid of this situation?
You shouldn't use the constructor to open the connection with the database.
Use the constructor only to instantiate other classes, initialize variables, allocate memory and so on.
In your case, your constructor should be used to initialize the database, but you could create another method with:
if(this->ueDatabase().open())
{
emit this->ueSignalDatabaseConnectionChanged(CONNECTED);
this->setQuery(UePosDatabase::UeSqlQueries::UeTablePeople::SQL_QUERY_GET_ALL_PEOPLE,
this->ueDatabase());
}
else
{
emit this->ueSignalDatabaseConnectionChanged(NOT_CONNECTED);
}
This method would be called after the connect you have in your main.cpp.
I've solved the problem by adding method void ueConnectToDatabase() and moved the content of constructor into it and redefined main.cpp as:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
UeStatus* ueApplicationStatus=new UeStatus(qApp);
UePeopleModel* uePeopleModel=new UePeopleModel(qApp);
QObject::connect(uePeopleModel,
SIGNAL(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)),
ueApplicationStatus,
SLOT(ueSignalDatabaseConnectionChanged(UeTypeDatabaseConnectionStatus)));
uePeopleModel->ueConnectToDatabase();
engine.rootContext()->setContextProperty("uePeopleModel",
uePeopleModel);
engine.rootContext()->setContextProperty("ueApplicationStatus",
ueApplicationStatus);
engine.addImageProvider(QLatin1String("uePeopleModel"),
uePeopleModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Now the object is created, signal and slot connected and AFTER this the connection to database occurs.

QNetworkManager uploading file to FTP crash

I am trying to upload a simple test text file to a FTP server. In order to achieve this I am using QNetworkAccessManager, since QFtp has been deprecated in Qt 5.1.
I created a test.txt file in the programs directory and using QFile I am opening it as QIODevice::ReadWrite | QIODevice::Text.
The problem is when I set the connection and tell the QNetworkAccessManager to upload a file the program crashes ("FTPConnectionTest does not respond"). It happens both when I am trying to use an external FTP server or a local one created with FileZilla.
I connected all signals emitted by the reply (functions: uploadFinish, uploadProgress, uploadError) however no feedback is beeing captured.
Question: Is this problem lying on the side of FTP server or am I doing something wrong in my code?
Code snipped below:
Main.cpp
#include <QCoreApplication>
#include <ftp.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Ftp ftp;
return a.exec();
}
ftp.cpp
#include "ftp.h"
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <QFile>
#include <QUrl>
#include <QDebug>
Ftp::Ftp()
{
QFile file("test.txt");
if (file.open(QIODevice::ReadWrite | QIODevice::Text)) {
url = QUrl("ftp://127.0.0.1/test.txt");
url.setUserName("user");
url.setPassword("password");
qDebug() << "URL set" << url;
QNetworkAccessManager* nam = new QNetworkAccessManager();
qDebug() << "nam set";
QNetworkReply *rep = nam->put(QNetworkRequest(url), &file);
qDebug() << "after rep";
connect(rep, SIGNAL(finished()), this, SLOT(uploadFinish()));
connect(rep, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(uploadError(QNetworkReply::NetworkError)));
connect(rep, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(uploadProgress(qint64,qint64)));
}
else qDebug() << "failed to open";
}
void Ftp::uploadFinish()
{
qDebug() << "finished uploading file";
}
void Ftp::uploadProgress(qint64 a, qint64 b)
{
qDebug() << a << "/" << b;
}
void Ftp::uploadError(QNetworkReply::NetworkError state)
{
qDebug() << "State" << state;
}
See the QNetworkAccessManager::put documentation:
data must be opened for reading when this function is called and must remain valid until the finished() signal is emitted for this reply.
Your file object falls out of scope when the constructor finishes execution, so QNetworkAccessManager probably tries to read from object that is already deleted. You need to make file a class member variable or create it using QFile* file = new QFile().

Problems with function QTimer::singleShot

I am trying to record sound by QAudioInput. According to the doc in this website QAudioInput. But when I ran, it exported an empty-raw file. After checking, It seems like the function QTimer::singleShot didn't working ( I added statement qWarning << "Done" in void stopRecording() and It didn't display "Done" so I thought it had some mistake in QTimer::singleShot function ).
This is my code used to check function QTimer::singleShot
----Check.pro----
QT += core
QT -= gui
TARGET = Check
CONFIG += console
CONFIG -= app_bundle
TEMPLATE = app
SOURCES += main.cpp
HEADERS += test.h
-----test.h------
#ifndef TEST_H
#define TEST_H
#include <QCoreApplication>
#include <QTimer>
#include <iostream>
#include <QObject>
#include <test.h>
#include <QDebug>
using namespace std;
class Object: public QObject {
Q_OBJECT
private slots:
void func() { cout << "Hello"; }
};
#endif // TEST_H
----main.cpp----
#include <QCoreApplication>
#include <QTimer>
#include <iostream>
#include <QObject>
#include <test.h>
#include <QDebug>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Object *o = new Object;
QTimer::singleShot(10000, o, SLOT(func()));
return 0;
}
And this code doesn't working, too. Can anyone explain me? I am newbie at Qt-programming.
Your program exits right after it's set the timer - it has no time to fire.
For the timer to work, you need an event loop running. Without the event loop, no events get processed.
Change the last line of your main to
return a.exec();
Also change your test slot by adding << std::endl or flush std::cout otherwise you might see no output on the console.
Your program should then work as expected (except it won't ever finish since nothing will cause the event loop to stop - just interrupt it).

Resources