I try to implement my own server class inheriting QTcpServer.
here is the simple code i try to run :
server.cpp
MyServer::MyServer(QObject *parent) :
QTcpServer(parent)
{
}
void MyServer::incomingConnection(qintptr handle)
{
qDebug() << "Incomming";
SecureSocket * socket = new SecureSocket(this);
connect(socket, SIGNAL(StatusMessage(QString)), SIGNAL(StatusMessage(QString)));
socket->Process(handle);
}
main.cpp
MyServer serv;
if(serv.listen(QHostAddress::Any,1080))
console.WriteLine("Listenning on port 1080..."); //Console it's just a class to display message (here it's a simple qDebug())
else {
console.WriteLine("Unable to start server");
}
QThread serverThread;
QObject::connect(&serverThread,SIGNAL(finished()),&serverThread,SLOT(deleteLater()));
serv.moveToThread(&serverThread);
My problem is that I never reach the incommingConnection (I try a https://localhost:1080 in my browser as test client) and I actually don't understand why. The server seems to listen properly because as long as the application run, my browser try to load the page, and set a loading error when I quit the application.
P.S. : It's a console application
Related
I am having a hard time getting to understand the non-standard C++ world that is qt. I have a class that can emit a 'login' signal, that I want to listen to from QML, this simply segfaults.
class Service : public QObject
Q_OBJECT
{
public:
Service()
{
// get the context, snipped for brevity
rootContext->setContextProperty("service", this);
}
public signals:
void login(bool succcess);
public slots:
void method();
};
I can successfully call 'service.method' from the QML, but if I add a Connections section to listen for the login event, I get a segfault whenever that component is displayed.
Page {
Component {
Column {
...
Connections {
target: service
onLogin: {
console.login("TEST");
}
}
}
}
}
I have tried moving the 'Connections' section out of the columns, but this results in a runtime-error and a white page, because it fails to parse the QML. What am I missing here?
I am using QT Creator 4.2.1 if that is in any way relevant.
Found the problem. Apparantly you cannot have a slot and a signal by the same name - even if they have wildly different function signatures. It doesn't give a compile error, it simply crashes.
After changing the name of the signal it magically started working.
I am trying to download a file, publicly available over an HTTPS URL, using Qt 4.8. I am behind a corporate authenticating proxy (over which I have no control).
I am using QNetworkAccessManager, as shown below:
bool FileDownloader::download(const QString& fileUrl, const QString& fileName)
{
QString outputFileName = fileName.isEmpty() ? fileNameFromUrl(fileUrl) : fileName;
_file.setFileName(outputFileName);
_file.open(QIODevice::WriteOnly);
QUrl url(fileUrl);
QNetworkReply* pReply = _networkAccessManager.get(QNetworkRequest(url));
pReply->ignoreSslErrors();
connect(pReply, SIGNAL(finished()), _pEventLoop, SLOT(quit()));
connect(pReply, SIGNAL(readyRead()), this, SLOT(onReadyRead()));
connect(pReply, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(onSslErrors(const QList<QSslError>&)));
connect(pReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onError(QNetworkReply::NetworkError)));
_pEventLoop->exec();
return true;
}
As soon as I call QNetworkAccessManager::get(), and receive a QNetworkReply object, I connect to its sslErrors signal as mentioned in the docs. Following the same docs, I'm also calling ignoreSslErrors() in the slot connected to that signal:
void FileDownloader::onSslErrors(const QList<QSslError>& sslErrors)
{
QNetworkReply* pReply = (QNetworkReply*)(sender());
pReply->ignoreSslErrors(sslErrors);
}
However, I never receive an sslErrors signal, I always get an error signal, which I'm handling in the onError slot, and which always says:
SSL handshake failed
I'm calling the download functionality thus:
FileDownloader fileDownloader;
fileDownloader.setProxy("http://username:password#proxyserver:8080");
fileDownloader.download(
"https://679cc07dd5c2e4623d32-c8530501a6bee9a6c1860bbdab5cb6f1.ssl.cf2.rackcdn.com/9807/05377d04583309a88e808df5a1758e4e.png",
"f:\\temp\\test.png"
I do not want to use other libraries like libcurl because I don't want to introduce dependencies.
So how can I download the file over HTTPS using Qt?
I am designing server/clients system for my own. I create a class with extending from QTcpServer and define QMap <ClientName, int> sockets to handle connected clients. Clients can connect to server when sockets map doesn't contains socket with same ClientName as new client. So, when new socket connects to server, I store client Pair <ClientName, SocketDescriptor> in qmap. With these explanation, I should remove client descriptor from qmap when client disconnects from server. So, I create slot void disconnected() and implement it as follow:
void MyServer::disconnected()
{
QTcpSocket* socket = (QTcpSocket*) sender();
ClientType socketType = ClientTypeNone;
foreach(ClientType key, _sockets.keys())
{
if (sockets.value(key) == socket.socketDescriptor())
{
socketType = key;
break;
}
}
if (socketType != ClientTypeNone)
{
sockets.remove(socketType);
}
}
But, socket.socketDescriptor is -1, while I've set it in below code:
void MyServer::inComingConnection(qintptr socketDescriptor)
{
QTcpSocket* socket = nextPendingConnection();
connect(s, SIGNAL(readyRead()), this, SLOT(readyRead());
connect(s, SIGNAL(disconnected()), this, SLOT(disconnected());
socket->setSocketDescriptor(socketDescriptor);
}
What was it wrong ?
This is the QT Assistant answer,maybe help,
qintptr QTcpServer::socketDescriptor() const
Returns the native socket descriptor the server uses to listen for incoming instructions, or -1 if the server is not listening.
If the server is using QNetworkProxy, the returned descriptor may not be usable with native socket functions.
I think your function inComingConnection should be renamed to incomingConnection to become a valid override one.
But why you're not let Qt setting the descriptor for you?
Accordingly to the Qt Documentation:
void QTcpServer::incomingConnection(qintptr socketDescriptor)
... The base implementation creates a QTcpSocket, sets the socket
descriptor and then stores the QTcpSocket in an internal list of
pending connections. Finally newConnection() is emitted. ...
so that you could simply use addPendingConnection instead:
void MyServer::addPendingConnection(QTcpSocket *s)
{
QTcpServer::addPendingConnection(s);
connect(s, SIGNAL(readyRead()), this, SLOT(readyRead());
connect(s, SIGNAL(disconnected()), this, SLOT(disconnected());
}
We have created a test suite and in order to run it we are using embedded Grizzly Web Server with JerseyTest framework.
We are extending a custom class from JerseyTest and in its constructor we are creating ApplicationDescriptor and then call superclass setupTestEnvironment() which essentially starts embedded grizzly web server.
Few of our test cases are extending this custom class to start grizzly server directly. However, we are not stopping this embedded server anywhere in the code.
The test cases run fine on windows but on Unix they fail with java.net.BindException port 9998 is in use by another process.
It becomes obvious these tests should fail with similar error on windows too if we are not stopping embedded web server in the code. How they are running fine on windows and failing on unix. Has this something to do with how Unix spawns threads or processes?
P.S. We have also tested whether port 9998 is in use by some other process using netstat -a | grep 9998 but no other process using that port could be found.
i had a similar problem and i did fix it by not using the default port if already used. just add following code to your test case:
#Override
protected int getPort(int defaultPort) {
ServerSocket server = null;
int port = -1;
try {
server = new ServerSocket(defaultPort);
port = server.getLocalPort();
} catch (IOException e) {
// ignore
} finally {
if (server != null) {
try {
server.close();
} catch (IOException e) {
// ignore
}
}
}
if ((port != -1) || (defaultPort == 0)) {
return port;
}
return getPort(0);
}
I had the same problem, when I was writing my integration tests. I didn't get to test on a Windows machine, but on my Unix machine I found the problem was that by default the JerseyTest class utilizes #After on it's tearDown method to close the embedded server. Since I had overridden this method to do clean up on my side, I had to call super.tearDown()
#After
public void tearDown() throws Exception{
super.tearDown();
...
}
After doing this, everything worked as expected.
I'm writing an application using Qt4.
I need to download a very short text file from a given http address.
The file is short and is needed for my app to be able to continue, so I would like to make sure the download is blocking (or will timeout after a few seconds if the file in not found/not available).
I wanted to use QHttp::get(), but this is a non-blocking method.
I thought I could use a thread : my app would start it, and wait for it to finish. The thread would handle the download and quit when the file is downloaded or after a timeout.
But I cannot make it work :
class JSHttpGetterThread : public QThread
{
Q_OBJECT
public:
JSHttpGetterThread(QObject* pParent = NULL);
~JSHttpGetterThread();
virtual void run()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
m_pHttp->setHost("127.0.0.1");
m_pHttp->get("Foo.txt", &m_GetBuffer);
exec();
}
const QString& getDownloadedFileContent() const
{
return m_DownloadedFileContent;
}
private:
QHttp* m_pHttp;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
private slots:
void onRequestFinished(int Id, bool Error)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
}
};
In the method creating the thread to initiate the download, here is what I'm doing :
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait();
But that doesn't work and my app keeps waiting. It looks lit the slot 'onRequestFinished' is never called.
Any idea ?
Is there a better way to do what I'm trying to do ?
Instead of using a thread you can just go into a loop which calls processEvents:
while (notFinished) {
qApp->processEvents(QEventLoop::WaitForMore | QEventLoop::ExcludeUserInput);
}
Where notFinished is a flag which can be set from the onRequestFinished slot.
The ExcludeUserInput will ensure that GUI related events are ignored while waiting.
A little late but:
Do not use these wait loops, the correct way is to use the done() signal from QHttp.
The requestFinished signal from what I have seen is just for when your application has finished the request, the data may still be on its way down.
You do not need a new thread, just setup the qhttp:
httpGetFile= new QHttp();
connect(httpGetFile, SIGNAL(done(bool)), this, SLOT(processHttpGetFile(bool)));
Also do not forget to flush the file in processHttpGetFile as it might not all be on the disk.
you have to call QThread::quit() or exit() if you are done - otherwise your thread will run forever...
I chose to implement David's solution, which seemed to be the easiest.
However, I had handle a few more things :
I had to adapt the QEventLoop enum values for Qt4.3.3 (the version I'm using);
I had to track the request Id, to make sure to exit the while loop when the download request is finished, and not when another request is finished;
I added a timeout, to make sure to exit the while loop if there is any problem.
Here is the result as (more or less) pseudo-code :
class BlockingDownloader : public QObject
{
Q_OBJECT
public:
BlockingDownloaderBlockingDownloader()
{
m_pHttp = new QHttp(this);
connect(m_pHttp, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool)));
}
~BlockingDownloader()
{
delete m_pHttp;
}
QString getFileContent()
{
m_pHttp->setHost("www.xxx.com");
m_DownloadId = m_pHttp->get("/myfile.txt", &m_GetBuffer);
QTimer::singleShot(m_TimeOutTime, this, SLOT(onTimeOut()));
while (!m_FileIsDownloaded)
{
qApp->processEvents(QEventLoop::WaitForMoreEvents | QEventLoop::ExcludeUserInputEvents);
}
return m_DownloadedFileContent;
}
private slots:
void BlockingDownloader::onRequestFinished(int Id, bool Error)
{
if (Id == m_DownloadId)
{
m_DownloadedFileContent = "";
m_DownloadedFileContent.append(m_GetBuffer.buffer());
m_FileIsDownloaded = true;
}
}
void BlockingDownloader::onTimeOut()
{
m_FileIsDownloaded = true;
}
private:
QHttp* m_pHttp;
bool m_FileIsDownloaded;
QBuffer m_GetBuffer;
QString m_DownloadedFileContent;
int m_DownloadId;
};
I used QNetworkAccsessManager for same necessity. Because this class managing connections RFC base (6 proccess same time) and non-blocking.
http://qt-project.org/doc/qt-4.8/qnetworkaccessmanager.html
How about giving the GUI some amount of time to wait on the thread and then give up.
Something like:
JSHttpGetterThread* pGetter = new JSHttpGetterThread(this);
pGetter->start();
pGetter->wait(10000); //give the thread 10 seconds to download
Or...
Why does the GUI thread have to wait for the "downloader thread" at all? When the app fires up create the downloader thread, connect the finished() signal to some other object, start the downloader thread, and return. When the thread has finished, it will signal the other object which can resume your process.