Seite 1 von 1
QTcpSocket mit Threads
Verfasst: 7. Juni 2006 16:26
von WeeZer
Hallo,
ich hänge immer noch an meinem Thread Problem. Da ich zuvor noch nie mit Threads gearbeitet habe, bin ich etwas hilflos und finde keinen richtigen Anfang.
Ich möchte eine Tcp Verbindung zu einem TeamSpeak Server aufmachen, und mich auf dem Server einloggen und befehle ausführen können und sie dann auswerten.
Wie geht man in so einem Fall vor?
Erstellt man für jede Aufgabe einen eigenen Thread (einen zum einloggen, einen um die Playerliste zu holen, usw.) oder erstellt man einen Thread der alle Aufgaben kann.
Bei der ersten Variante weiß ich nicht, wie mehrere Threads gemeinsam einen QTcpSocket nutzen können, weil ich den Socket ja in dem Thread selbst erstellen muss, damit ich ihn dort benutzen kann.
Und bei der zweiten schaffe ich es nicht, dass der Thread mehr als eine Sache kann, und ich ihm sage was er machen soll.
MfG
Felix
Verfasst: 7. Juni 2006 16:42
von patrik08
Schaue dir doch den source an von ...
http://sourceforge.net/projects/tsdisplay
dann kannst du erzahlen wie der protocoll ist... oder vielleicht noch etwas source code auftischen....
Verfasst: 7. Juni 2006 17:16
von WeeZer
Da habe ich wohl meine Frage falsch formuliert.
Ich brauche keine Hilfe um mit dem TeamSpeak Server zu kommunizieren, ich weiß nur nicht wie ich einen QTcpSocket in Verbindung mit Threads benutze.
Wie ich in meinem ersten Beitrag schon geschrieben habe, ich weiß nicht ob ich mehrere Threads benötige, die alle eine Aufgabe erledigen (einen Thread der mich ins Telnet Interface von TeamSpeak einloggt und dann noch weitere, die die Daten von dem Server holen, die ich brauche und welche die meine Befehle an den Server senden) oder ob ein Thread all diese Sache alleine machen kann.
Verfasst: 7. Juni 2006 17:21
von patrik08
wenn du mit diesem server via telnet abfragen kannst dann folge doch
das smtp beispiel.....
http://www.qtforum.de/forum/viewtopic.php?t=2172
Du musst dir selber fragen wass besser ist QTcpSocket mit Threads oder ohne...
Verfasst: 7. Juni 2006 17:59
von WeeZer
Eigentlich habe ich schon entschieden es mit Threads zu machen und da hilft mir dein Beispiel leider nicht direkt weiter, aber ich werde es mir mal genauer anschauen.
Es geht mir wirklich nur darum wie ich einen QTcpSocket in einem QThread benutze. Oder noch viel genereller wie ich QThreads benutze, wie ich mit ihnen interagiere.
Ich habe in der Dokumentation schon alles gelesen was ich zu Threads gefunden habe, aber das hat meine Fragen auch nicht beantwortet, da in allen Beispielen aus der Doku die Anwendungen immer nur eine Sache mit den Threads machen.
Zum Beispiel verbinden sie sich nur zu einem Server und holen dann eine Nachricht ab. Aber ich muss mehrere Sachen erledigen, mich einloggen, und je nachdem wie meine Anwendung es gerade braucht bestimmte Daten vom Server holen oder senden.
Verfasst: 8. Juni 2006 07:24
von DarkWotan
Generell gilt:
verwende Threads nur dann, wenn eine Aufgabe a auf eine Ressource zugreift und auf diese wartet und dadurch eine Aufgabe b, die im Programmfluss danach ausgeführt würde, blockiert, obwohl b auf eine ganz andere Ressource zugreifen muss.
Verwende Threads nicht, wenn lediglich die CPU bei der Bearbeitung zweier Routinen aktiv ist bzw. diese auf die gleiche Ressource zugreifen, da dies keinen Geschwindigkeitsvorteil bringt.
Ich habe mich mit Threading in Qt noch nicht so intensiv beschäftigt, aber ich weiß, dass es von der Programmstruktur her Java stark ähnelt, d. h. eine Klasse von QThread ableiten und die run()-Methode mit dem in dem Thread auszuführenden Code implementieren.
Ich habe in Java mal einen threaded Server geschrieben, vielleicht hilft dir das weiter, da es normal auf Qt auch anzuwenden sein müsste:
http://pastebin.de/7316
MfG, Cedric
Verfasst: 9. Juni 2006 20:03
von WeeZer
Ich habe in Java mal einen threaded Server geschrieben, vielleicht hilft dir das weiter, da es normal auf Qt auch anzuwenden sein müsste:
http://pastebin.de/7316
Ich habe mir deinen Server mal angeschaut, nur leider hat er mir auch nicht viel weiter geholfen. Mein Problem ist das ich dem Thread von außerhalb sagen muss was er tun soll, in deinem Server ergibt sich das ja in dem Thread selbst, wenn er die Eingabe des Client einließt.
Ich könnte es so machen, das ich einen Integer außerhalb des Threads setze, und in dem Thread dann schaue auf was der Integer steht, und daran erkenne ich dann im Thread was er machen soll. Zum Beispiel 1: logge dich ein, 2: hole dir die Playerlist und so weiter. Allerdings finde ich das dies eine sehr unsaubere Lösung ist.
Ich habe auch schon versucht mehrere Threads zu benutzen, für jede Aufgabe einen eigenen. Nur ist dabei mein Problem, dass alle Threads den selben QTcpSocket brauchen, und um den QTcpSocket in einem Thread verwenden zu können, muss ich den auch in dem Thread erstellen.
Wie stelle ich es an, den selben QTcpSocket in mehreren Threads zu verwenden?
Verfasst: 9. Juni 2006 21:41
von patrik08
WeeZer hat geschrieben:Eigentlich habe ich schon entschieden es mit Threads zu machen und da hilft mir dein Beispiel leider nicht direkt weiter, aber ich werde es mir mal genauer anschauen..
Mache es wie du gerne moechtest....
Schade Kanns du nicht php lesen

... den vollen code von
http://sourceforge.net/projects/tsdisplay
Mit eine simple
http://php.net/fsockopen verbindet das script zum server..
Warum einfach machen wenn es Kompliziert auch geht!
Code: Alles auswählen
// Opens a connection to the teamspeak server
function _openConnection(&$socket, $host, $port, $timeout) {
@$socket = fsockopen($host, $port, $errno, $errstr, $timeout);
if ($socket and ($this->_stripEOL(fgets($socket, 4096)) == "[TS]")) {
return true;
} else {
return false;
}
}
und noch einfacher geht es weiter....
Verfasst: 9. Juni 2006 22:10
von WeeZer
Danke, aber das ist gar nicht meine Frage. Ich brauche wirklich keine Hilfe um mit dem TeamSpeak Server zu kommunizieren. In dem Bereich habe ich genug Erfahrung. Mir geht es allein um QThreads in Verbindung mit einem QTcpSocket, ob ich mit dem QTcpSocket zu einem TeamSpeak Server verbinde oder nicht ist erst mal egal.
Verfasst: 11. Juni 2006 20:39
von Eltharion
Du solltest Dir zuerst überlegen, was genau im Thread separiert werden soll. Wenn es die Kommunikation mit dem Server ist (z.B. weil das Warten auf Netzwerk-IO die grafische Oberfläche blockiert), dann gehört das Socket auch in den Thread. Mehrere Threads und Socket-Sharing sind nicht nötig, da Du ja mit einem Thread nebenläufig etwas tun willst um den Haupt-Thread, also in dem Fall wohl Dein GUI zu entlasten. Ein extra Thread pro Action (einloggen, irgendwas hinsenden) ist hier nicht nötig, da man solche Aufgaben in der Regel hintereinander ausführt. Wichtig ist in Deinem Fall, dass Dein Thread eine extra Messageloop hat (also exec() aufruft), damit QTcpSocket überhaupt funktioniert und damit Mitteilungen von der Anwendung zum Thread und umgekehrt gehen können. Dazu kannst Du aber seit Qt4 die ganz normalen connect()-Aufrufe benutzen. Also extra Event-Klassen und jede Menge unnötiger Aufwand fallen da in den neueren Qt-Versionen weg.
E*
Verfasst: 12. Juni 2006 13:31
von DarkWotan
Eltharion hat ganz Recht.
Da du ja vorhast, einen Client zu schreiben, wird ja auch nur eine einzige Socket-Verbindung zum TeamSpeak-Server nötig sein.
Wie Eltharion schon sagte, ist Threading hier nur sinnvoll, wenn Netzwerk-IO die GUI blockieren würde.
Angenommen, du würdest drei Threads für eine einzige Ressource (die TCP-/UDP-Verbindung) verwenden, brächte es dir gegenüber einem einzigen Thread genau gar keinen Geschwindigkeitsvorteil, weil du mit Mutexes arbeiten müsstest, um die Threads synchron zu halten. Mutex aller drei Threads bei einer einzigen Ressource == serielle statt parallele Abarbeitung der Operationen == effektiv nur ein Thread.
Thread 1: GUI (Fenster aufbauen, User-Nachrichten verarbeiten, etc.)
Thread 2: Netzwerk (Verbindung aufbauen, einloggen, kommunizieren...)
Mehr ist nicht nötig.
Solltest du aus irgendeinem Grund von einem anderen Thread aus auf die Netzwerkressource zugreifen müssen, lege die doch einfach global für beide Threads an und übergebe einen Zeiger auf diese an den Konstruktor der Threads, so wie in meinem Serverbeispiel.
MfG, Cedric
Verfasst: 12. Juni 2006 13:48
von Alci
@patrik08: Ich glaube, dass du das Problem nicht begriffen hast. Es geht nicht darum, wie man richtig eine Verbindung zu einem TeamSpeark-Server herstellt, sondern wie man Threads einsetzen soll/kann. Und schon klar, dass das mit PHP wesentlich einfacher geht, den PHP ist ja für solche Zwecke wesentlich besser geeignet, als ein übergreifendes Framework wie Qt.
Verfasst: 15. Juni 2006 17:20
von WeeZer
Solltest du aus irgendeinem Grund von einem anderen Thread aus auf die Netzwerkressource zugreifen müssen, lege die doch einfach global für beide Threads an und übergebe einen Zeiger auf diese an den Konstruktor der Threads, so wie in meinem Serverbeispiel.
Ich glaube das funktioniert so nicht, weil der QTcpSocket dann in einem anderen EventLoop als der von dem Thread läuft. Aber ihr habt mich überzeugt, mehrere Threads sind bei meinem Problem sowieso nicht sinnvoll.
Ich habe es jetzt so gemacht:
Ich habe nur einen Thread neben dem GUI Thread in dem ich eine "TsSocket" Klasse erstelle. Mein QTcpSocket ist member der TsSocket Klasse, und sie hat Slots, die die einzelnen Aufgaben erledigen.
Mein Thread hat auch die selben Slots wie mein TsSocket, diese feuern Signale, die mit den Slots der TsSocket Klasse verbunden sind.
Vielen Dank für eure Hilfe!