Seite 1 von 1
QSocket: Signal "connectionClosed()" nix passiert
Verfasst: 12. Januar 2006 14:14
von webbasti
Hallo!
Ich habe einen Client implementiert, der zunächst zwei Signale initiert.
myObject.connect( myObject.testSocket, SIGNAL(readyRead()), SLOT(handleInput()) );
myObject.connect( myObject.testSocket, SIGNAL(connectionClosed()),SLOT(connClosed()) );
sowie entsprechende SLOTS:
public slots:
void handleInput();
void connClosed();
Nachdem ich eine Verbindung hergestellt habe, habe ich eine Endlosschleife implementiert.
Wenn ich dort "nichts" mache, wird keinerklein Signal erzeugt bzw. Slot aufgerufen wenn Bytes ankommen. Wenn ich dort ein
testSocket->bytesAvailable();
einbaue (was quasi dauerhaft aufgerufen wird dann, ohne Auswertung)
dann wird das Signal "ReadyRead()" bei empfangenen Zeichen ausgelöst.
Aber nur dann!
Das Signal "connectionClosed()" wird nie ausgelöst. Auch beim Beenden der Serverseite passiert nichts!
Woran kann das liegen??
Danke Euch!
Verfasst: 12. Januar 2006 14:40
von Christian81
Ist es nicht einfacher einen QSocketNotifier dafür zu benutzen?
Re: QSocket: Signal "connectionClosed()" nix passi
Verfasst: 12. Januar 2006 14:42
von macman
webbasti hat geschrieben:Nachdem ich eine Verbindung hergestellt habe, habe ich eine Endlosschleife implementiert.
Aua. Qt liefert ein ganzes Bündel Netzwerkbeispiele mit. Schau dir die mal an.
Re: QSocket: Signal "connectionClosed()" nix passi
Verfasst: 12. Januar 2006 15:15
von webbasti
Das mit dem QSocketNotifier klingt interessant. Werd ich mal probieren.
Aber wieso "Aua"? Ich brauche eine Schleife, da ich in regelmäßigen Abständen in einer Datenbank Daten abfragen muss und diese dann über die Socket senden muss. Okay, ich könnte ein Timer einsetzen, aber ich baruche ja eine Möglichkeit, meinen Prozess am Laufen zu halten..
Ach ja - vielleicht solle ich erwähnen, dass ich die QT-Programm als Konsolenprogramm laufen lasse - keine GUI-Anwendung!!
Verfasst: 12. Januar 2006 15:19
von Christian81
Trotzdem sollte man im Eventloop bleiben und nicht irgendwleche selbstgebastelten Schleifen benutzen...
Re: QSocket: Signal "connectionClosed()" nix passi
Verfasst: 12. Januar 2006 15:31
von macman
webbasti hat geschrieben:Aber wieso "Aua"? Ich brauche eine Schleife, da ich in regelmäßigen Abständen in einer Datenbank Daten abfragen muss und diese dann über die Socket senden muss.
So lange Du aber in deiner Schleife bleibst, kann deine App nichts anderes tun, also auch keine Signale senden. Du könntest natürlich ein doEvents in die Schleife packen, aber schön ist das nicht. So eine Endlosschleife erzeugt nur unnötig Prozessorlast und die Datenbank findet das bestimmt auch nicht toll, so schnell wie möglich abgefragt zu werden

Eventloop
Verfasst: 12. Januar 2006 15:32
von webbasti
Danke erst mal für Eure Antworten!
Mhh. und wie komme ich denn nun in den Eventloop?
Unter einem GUI-Programm ging das ja mit MainWindow anzeigen und
"return myApp.exec()"
Ich habe mir schon einige Netzwerkbeispiele angeschaut. Ich möchte einfach nach der erfolgreichen Verbindung diese aufgebaut lassen und auf SIGNALE reagieren. Wenn keine Schleife, wie dann? Wie komme ich in die QT-EventLoop. Habe eine reine Konsolen-Anwendung.
Verfasst: 12. Januar 2006 15:47
von Christian81
Qt4: QCoreApplication
Qt3: qApp->processEvents()
Du musst in die Eventloop damit Qt seine Signals/Slots und Socketnotifiers verarbeiten kann.
EventLoop
Verfasst: 12. Januar 2006 16:19
von webbasti
Okay soweit verstanden. Danke! Aber es klappt noch nicht.
Was genau muss denn jetzt an den Schluss meiner Main-Methode?
"myApp->processEvents()" führt zu nichts und das Programm wird danach beendet.
meine Main-Methode im GROBEN:
main() {
(...)
myClass myObj;
myObj.testSock->connectToHost ("localhost",8060);
myObj.testSock->writeBlock(xml,xml.length());
// ab hier soll der Socket offen bleiben und das Prg auf Anfragen reagieren
myApp->processEvents();
}
habe es auch mit der Funktion "eventLoop()" statt processEvents() probiert...dabei wird das Programm zwar nicht beendet, es werden aber auch keine SIGNALE ausgeführt.
Verfasst: 12. Januar 2006 16:29
von Christian81
Irgendwas in der Form
Code: Alles auswählen
do {
qApp->processEvents();
sleep(1);
} while(!bFertig)
Und bFertig wird dann von Dir auf true gesetzt wenn Deine Übertragung abgeschlossen ist und das Programm beendet werden soll.
Das sleep(1) ist dazu da damit dein Programm nicht 100% CPU-Last benutzt und auch mal Pause macht

geht nicht
Verfasst: 12. Januar 2006 16:49
von webbasti
Ja, so hatte ich mir das auch schon überlegt..
geht nicht.
Es passiert einfach nichts. Die Slots werden nicht aufgerufen, obwohl ich Daten hinschicke.
==============================================
Hier mal der komplette Code
CPP-Datei:
==============================================
Code: Alles auswählen
#include <qapplication.h>
#include <qdom.h>
#include <qfile.h>
#include <qstring.h>
#include <qsocket.h>
#include <stdio.h>
#include "myClient.h"
void MySpecialHost::handleInput() {
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "handleInput!!!";
}
void MySpecialHost::connClosed() {
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "connClosed bzw error!!!";
}
void MySpecialHost::connOpen() {
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "Connection-OpenSignal.";
}
int main(int argc, char *argv[])
{
QApplication myApp( argc, argv, FALSE ); // ohne GUI
MySpecialHost MySpecialH;
QTextStream ausgabe ( stdout, IO_WriteOnly);
QString xml = "Nachricht an den Server!";
ausgabe << "\n-----SOCKET AUFBAU-----------\n";
MySpecialH.testSock->connectToHost ("localhost",8060);
MySpecialH.testSock->writeBlock(xml,xml.length());
MySpecialH.testSock->flush();
ausgabe << "\n-----PROCESS EVENTS-----------\n";
do {
myApp.processEvents();
} while(1); // bricht nie ab!! NUR zum Testen
MySpecialH.testSock->close();
return myApp.exec();
}
=========================================
Header:
=========================================
Code: Alles auswählen
#include <qapplication.h>
#include <qdom.h>
#include <qfile.h>
#include <qstring.h>
#include <qsocket.h>
#include <stdio.h>
class MySpecialHost : public QObject
{
Q_OBJECT
public:
MySpecialHost()
{
testSock = new QSocket(this);
connect( testSock, SIGNAL(connected()),SLOT(connOpen()) );
connect( testSock, SIGNAL(readyRead()), SLOT(handleInput()) );
connect( testSock, SIGNAL(connectionClosed()),SLOT(connClosed()) );
connect( testSock, SIGNAL(delayedCloseFinished()), SLOT(connClosed()) );
}
QSocket* testSock;
int main(int argc, char *argv[]);
public slots:
void handleInput();
void connClosed();
void connOpen();
};
Verfasst: 13. Januar 2006 08:05
von Christian81
Und wie schaut dein Server aus?
QTextStream() ist auch nicht so gut da es evtl. nicht auf der Konsole ausgegeben wird. Nimm lieber QMessageBox().
Und bitte benutze die 'code' - Tags hier im Forum oder hänge es als Datei an. So kann man ja nichts korrekt lesen.
Endeckungen & Server-Code
Verfasst: 13. Januar 2006 10:55
von webbasti
Also beim Server funktionieren die SIGNALE/SLOTS...
Beim Client habe ich die Schleife nun wie folgt angepasst:
Code: Alles auswählen
do {
MySpecialH.testSock->waitForMore(0);
app.processEvents();
int bAnew=MySpecialH.testSock->bytesAvailable();
if (bAnew!=bA) {
ausgabe << bAnew;
bA=bAnew;
}
} while(1);
Wenn ich die "WaitForMore"-Funktion reinnehme, wird mir das Connected und Close-Signal ausgegeben. NUR das BytesReady-Signal wird nicht ausgelöst. Mit bytesAvailable konnte ich aber feststellen, dass Daten reingekommen sind. Kann natürlich nun einfach "if BytesReady>0 ---> Funktion aufrufen" in die Schleife einfügen. Aber das wäre wieder unsauber.
Hier mal der Server-Code:
server.h:
Code: Alles auswählen
#include <qsocket.h>
#include <qserversocket.h>
#include <qapplication.h>
#include <qtextstream.h>
#include <stdlib.h>
/*
The ClientSocket class provides a socket that is connected with a client.
For every client that connects to the server, the server creates a new
instance of this class.
*/
class ClientSocket : public QSocket
{
Q_OBJECT
public:
ClientSocket( int sock, QObject *parent=0, const char *name=0 ) :
QSocket( parent, name )
{
line = 0;
connect( this, SIGNAL(readyRead()),
SLOT(readClient()) );
connect( this, SIGNAL(connectionClosed()),
SLOT(deleteLater()) );
setSocket( sock );
}
~ClientSocket()
{
}
signals:
void logText( const QString& );
private slots:
void readClient()
{
QTextStream ts( this );
while ( canReadLine() ) {
QString str = ts.readLine();
emit logText( tr("Read: '%1'\n").arg(str) );
ts << line << ": " << str << endl;
emit logText( tr("Wrote: '%1: %2'\n").arg(line).arg(str) );
line++;
}
}
private:
int line;
};
/*
The SimpleServer class handles new connections to the server. For every
client that connects, it creates a new ClientSocket -- that instance is now
responsible for the communication with that client.
*/
class SimpleServer : public QServerSocket
{
Q_OBJECT
public:
SimpleServer( QObject* parent=0 ) :
QServerSocket( 8060, 1, parent )
{
if ( !ok() ) {
qWarning("Failed to bind to port 4242");
exit(1);
}
}
~SimpleServer()
{
}
void newConnection( int socket )
{
ClientSocket *s = new ClientSocket( socket, this );
emit newConnect( s );
}
signals:
void newConnect( ClientSocket* );
};
/*
The ServerInfo class provides a small GUI for the server. It also creates the
SimpleServer and as a result the server.
*/
class ServerInfo : public QObject
{
Q_OBJECT
public:
ServerInfo()
{
SimpleServer *server = new SimpleServer( this );
connect( server, SIGNAL(newConnect(ClientSocket*)),
SLOT(newConnect(ClientSocket*)) );
}
QSocket *clientSock;
~ServerInfo()
{
}
private slots:
void newConnect( ClientSocket *s )
{
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "\nnewConnect";
clientSock=s;
// infoText->append( tr("New connection\n") );
//connect( s, SIGNAL(logText(const QString&)),
//infoText, SLOT(append(const QString&)) );
connect( s, SIGNAL(connectionClosed()),
SLOT(connectionClosed()) );
connect( s, SIGNAL(readyRead()),
SLOT(connectionInput()) );
}
void connectionClosed()
{
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "\nconnectionClosed";
}
void connectionInput( )
{
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "\nconnectionInput";
int tempBytesAvailable = clientSock->bytesAvailable();
ausgabe << "\nBytesAvailable:";
ausgabe << tempBytesAvailable;
ausgabe << "\nRead: ";
char *inputData=new char[1000];
int bytesRead=clientSock->readBlock(inputData, tempBytesAvailable);
ausgabe << inputData;
ausgabe << "\nSend #1... ";
int bytesWritten=clientSock->writeBlock(inputData, tempBytesAvailable);
ausgabe << "\nFlush... ";
clientSock->flush();
}
};
server.cpp:
Code: Alles auswählen
#include <qsocket.h>
#include <qserversocket.h>
#include <qapplication.h>
#include <qtextstream.h>
#include <stdlib.h>
#include "MySpecialserver.h"
int main( int argc, char** argv )
{
QApplication app( argc, argv , 0);
ServerInfo info;
QTextStream ausgabe ( stdout, IO_WriteOnly);
ausgabe << "\nvor return";
//app.setMainWidget( &info );
//info.show();
return app.exec();
}