[gelöst] QTcpSocket::disconnectFromHost() - Problem

Alles rund um die Programmierung mit Qt
Antworten
Tom_Tom
Beiträge: 54
Registriert: 2. August 2008 18:39

[gelöst] QTcpSocket::disconnectFromHost() - Problem

Beitrag von Tom_Tom »

Hallo, ich habe folgendes Problem zu dem ich einfach keine Lösung finde.

Ich habe einen Server geschrieben, der jede eingehende Verbindung in einen extra Thread verwaltet.
Wenn ich dann den Server stoppen will und somit alle Verbindungen zu den Clients schließen will, schließt er bei mir nur immer die Hälfte der Verbindungen.

Hier die logout() - Methode von meinem Connection-Thread:

Code: Alles auswählen


ClientConnectionThread::ClientConnectionThread(QTcpSocket * socket, QList<ClientConnectionThread*> * clientConnectionThreadList, QObject* parent /*= 0*/ ) : QThread(parent) 
{ 
      this->clientConnectionThreadList = clientConnectionThreadList; 
      this->socket = socket; 
} 


void ClientConnectionThread::logout() { 
   this->socket->disconnectFromHost(); 
}




Hier der Code-Ausschnitt von meinem Server:

Code: Alles auswählen


MainWindow::MainWindow( QWidget* parent /*= 0*/, Qt::WFlags flags /*= 0*/ ) : QMainWindow(parent, flags) 
{ 
   setupUi(this); 
   this->tcpServer = new QTcpServer(this); 
   this->clientConnectionThreadList = new QList<ClientConnectionThread*>(); 

        if (this->tcpServer->listen(QHostAddress(this->lineEditServerHost->text()),this->spinBoxServerPort->value())) 
   { 
           connect(this->tcpServer,SIGNAL(newConnection()),this,SLOT(newClientConnection())); 
   } 


} 

void MainWindow::on_pushButtonServerStop_pressed() { 
   //stop TCP - Server 
    
   for(int i=0; i<this->clientConnectionThreadList->count(); i++) 
   { 
                //an dieser Stelle läuft er nur bis zur Hälfte der Liste und kann dann in der logout()-Methode nicht weiter disconnectFromHost() erfolgreich              
                  ausführen 
      clientConnectionThreadList->at(i)->logout(); 
   } 
    
   this->tcpServer->close(); 
} 


void MainWindow::newClientConnection() { 
   qDebug("new connection is available"); 

   QTcpSocket * socket = this->tcpServer->nextPendingConnection(); 
   ClientConnectionThread * clientConnectionThread = new ClientConnectionThread(socket, this->clientConnectionThreadList,this); 
    
   connect(clientConnectionThread,SIGNAL(finished()),clientConnectionThread,SLOT(deleteLater())); 
   clientConnectionThread->start(); 

   //add new ClientConnectionThread to List 
   this->clientConnectionThreadList->append(clientConnectionThread); 
} 

Wäre schön, wenn mir dort jemand weiterhelfen könnte.
Zuletzt geändert von Tom_Tom am 6. Oktober 2008 07:55, insgesamt 1-mal geändert.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

Ich sehe keinen offensichtlichen Fehler, hätte aber folgende Fragen:

1. wozu benötigt der ClientConnectionThread die Liste "clientConnectionThreadList"?
2. du rufst "disconnectFromHost" nicht vom ConnectionThread auf, sondern vom Mainthread ("MainWindow"). Warum?
3. was tut der ConnectionThread (Code der run-Methode?)
Tom_Tom
Beiträge: 54
Registriert: 2. August 2008 18:39

Beitrag von Tom_Tom »

Hallo.

Also zu 1: Ich übergebe den Zeiger auf clientConnectionThreadList mit, um später von dem einen Thread aus Zugriff auf die Member eines anderen Threads zu haben. Und damit jeder Unter-Thread von MainWindow die anderen Unter-Threads kennt, übergebe ich die Liste.

Zu 2: Ich rufe disconnectFromHost() nicht vom MainWindow, sondern von ConnectionThread auf. Von MainWindow rufe ich nur die logout()-Methode des ConnectionThreads auf, welche dann in der ConnectionThread disconnectFromHost() aufruft.

Zu 3: Die run()-Methode macht derzeit noch garnichts außer dass dort ein exec() aufgerufen wird. Später sollen darin die Anfragen des Clientes verarbeitet werden.

Ich weiß auch nicht, warum er eben immer nur exakt die Hälfte der Verbindungen trennt und die andere Hälfte nicht. Ist schon komisch.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

1. und 3. sind ok.. bei 2. habe ich diese leider diese Antwort erwartet.. du rufst disconnectFromHost() ueber MainWindow->ConnectionThreads->abort auf.. also im Hauptthread.. _nicht_ im ConnectionThread (dieser befindet sich ja in der Methode "exec()"). Korrekt waere also, wenn du diesem Thread ein Signal sendest, damit dieser selbst (!) die Verbindung abbauen kann.
kann dann in der logout()-Methode nicht weiter disconnectFromHost() erfolgreich ausführen
Ich sehe nirgends, wie der Thread-Status überprüft wird.. was meinst du denn damit genau? (wie verhält sich dein Programm und was würdest du erwarten).
mummy
Beiträge: 4
Registriert: 22. April 2008 22:53

QTcpSocket::disconnectFromHost() - Problem Antworten mit Z

Beitrag von mummy »

Hallo,

wenn nur genau die Hälfte der Sockets geschlossen wird deutet das auf einen Fehler in der Schleife hin. In on_pushButtonServerStop_pressed wird in der Schleife der Socket
geschlosen. Falls der Thread dann auch beendet wird, das geht aus dem Codefragment nicht hervor, wird zum einen die Schleifenvariabel i erhöht und der Endwert der Schleife ( ThreadList->count) erniedrigt. Dann ist nach genau der Hälfte schluß.

Ist aber nur ne Vermutung :-)

Code: Alles auswählen

void MainWindow::on_pushButtonServerStop_pressed() {
   //stop TCP - Server
   
   for(int i=0; i<this->clientConnectionThreadList->count(); i++)
   {
                //an dieser Stelle läuft er nur bis zur Hälfte der Liste und kann dann in der logout()-Methode nicht weiter disconnectFromHost() erfolgreich             
                  ausführen
      clientConnectionThreadList->at(i)->logout();
   }
   
   this->tcpServer->close();
}
Tom_Tom
Beiträge: 54
Registriert: 2. August 2008 18:39

Beitrag von Tom_Tom »

Also erstmal zu solarix:
Ich habe das jetzt so gemacht, wie du gesagt hast und noch ein

Code: Alles auswählen

connect(this->pushButtonServerStop,SIGNAL(pressed()),socket,SLOT(disconnectFromHostImplementation()));
eingebaut.

Jetzt funktioniert es auch. Danke dir nochmal.


Und nun zu mummy:

Deine Logik klingt garnicht so verkehrt. Das ganze müsste ich nochmal ausprobieren, ob das wirklich so ist.


Also nochmal vielen Dank für eure Hilfe.
Antworten