# Teamspeak-RemoteControlTool



## kniffel (5. Mai 2009)

Hello,
ich bin gerade an einem kleinen Projekt dran, nämlich beim basteln einer Console, damit ich mit einem Teamspeak-server kommunizieren kann. (Befehle senden, abfragen, Antworten->auslesen)

Mein Tool funktioniert auch einwandfrei, jedoch erlaubt er mir nur 1 Zeile aus dem BuffedReader auszulesen.
Habe es versucht mit ner While schleife, so lange auszulesen bis null zutrifft. Funktioniert nur zur Hälfte. Denn das Programm selbst (Oberfläche) hängt sich auf, aber davor wird der Befehl erfolgreich ausgeführt (System.out schreibt mir das ergebniss mehrzeilig aus).
Die Oberfläche bekommt aber nichts vom Kuchen ab. Habe es schon mit "neanderthalerischen" if's versucht - Ohne Erfolg, while-do Schleife - Ohne Erfolg.
Es müsste theoretisch die While schleife funktionieren, wäre super wenn jemand Tipps hat, oder einen Fehler sieht.
Habe es auch schon mit dem mark() und reset() versucht. Aber ging auch nicht 
Hier der Code:


```
try {
      String host = "host";
      Socket echoSocket = new Socket("localhost",51234);
      OutputStream socketoutstr = echoSocket.getOutputStream();
      OutputStreamWriter osr = new OutputStreamWriter( socketoutstr );
      BufferedWriter bw = new BufferedWriter( osr );
      InputStream socketinstr = echoSocket.getInputStream();
      InputStreamReader isr = new InputStreamReader( socketinstr );
      BufferedReader br = new BufferedReader( isr );
      String antwort;
      String anfrage;
      
      anfrage = "sl";
      bw.write(anfrage);
      bw.newLine();
      bw.flush();

while ((antwort = br.readLine()) != null) {
      tf.append(antwort);
      System.out.println(antwort);
     }//Ende while

     br.close();
     bw.close();
     echoSocket.close();

    }
    catch (UnknownHostException uhe) {
      System.out.println(uhe);
    }
    catch (IOException ioe) {
      System.out.println(ioe);
    }
```

Habe die eingabe vom Benutzer durch, einen festen Befehl ersetzt um das Problem einzugrenzen.
Der sl Befehl sollte erfolgreich dies zurückliefern:

8767
OK
Davor käme noch die Antwort:
[TS]

Danke vielmals für die Mühe, hier zu helfen.


----------



## sparrow (5. Mai 2009)

Wird die while-Schleife definitv verlassen?
Lass hinterher mal etwas ausgeben, nicht das der TS-Server die Verbindung nicht abbaut.


----------



## kniffel (5. Mai 2009)

Ja ich denke schon weil sl nur diese 2 Zeilen ausgibt und z.B. bei help nur 1x alle befehle gelistet werden, so wie es also sein sollte.
*EDIT
Doch nicht, du hast recht, setze ich ein System.out.println("Ende"); nach die while, wird es nicht mehr ausgegeben.
Okay, liegt also an der While schleife, die nicht verlassen wird. Wieso?
Er bricht bei null nicht ab obwohl das Ende erreicht ist. Stimmt der Ansatz?


----------



## sparrow (5. Mai 2009)

*null* wird nur dann vom Stream zurückgegeben wenn das Ende des Streams erreicht ist. In diesem Fall also wenn der Server die Verbindung abbaut.
Der Server baut aber die Verbindung nicht ab sondern hält sie offen. Wenn ich das richtig verstanden habe hast du bisher ja nur den Benutzer angemeldet und der Server sagt "Hallo, herlich willkommen. Mach mit mir was du willst.", und die Verbindung muss er offen halten damit du entsprechende Befehle an den Server senden kannst.

Vielleicht gibt es, genauso wie ein login, auch einen Befehl um die Verbindung wieder abzubauen?


----------



## kniffel (5. Mai 2009)

Wooow 
Danke lol du hast voll ins schwarze getroffen.

```
while ((antwort = br.readLine()) != null) {
      tf.append(antwort);
      System.out.println(antwort);
      anfrage = "quit";
      bw.write(anfrage);
      bw.newLine();
      bw.flush();
     }//Ende while
     System.out.println("Ende");
```

Sieht jetzt so aus und es funktioniert. Hattest recht, dass er die Verbindung so lange aufrecht hällt, damit ich ihm etwas übermitteln kann. Es tritt wie du gesagt hast kein *null* auf, weil die Verbindung ständig aufrecht gehalten wird. Erst mit quit und mit anschließendem erneut senden gehts weiter. Danke 

Bin jetzt gespannt ob das alles auch noch funktioniert, wenn ich mich einlogge um diverses zu ändern, ob es dann funktioniert, wenn er die Verbindung quittet.
Wenns nicht funktioniert, melde ich mich wieder.
Danke nochmal


----------



## sparrow (5. Mai 2009)

So funktioniert das aber nicht.
Im Augenblick sendest du nach jeder empfangenen Zeile ein quit.


----------



## kniffel (5. Mai 2009)

Ja, das ist mir klar. Es gibt aber keine andere möglichkeit irgendwie die verbindung abzubauen. Jedenfalls keine die mir bekannt sei. hmm


----------



## sparrow (5. Mai 2009)

Du sollst sie ja auch erst abbauen wenn die Verbindung nicht mehr benötigt wird.

Hast du schon einmal auf einer Kommandozeile gearbeitet?
Du gibst einen Befehl und der Computer antwortet etwas.
Genauso funktioniert das hier auch.

Das beenden der Verbindnug (bzw. das senden von quit) entspricht aber dem beenden der Kommandozeile. Also kannst du ab dem Moment auch keine Befehle mehr senden.
Dein Problem ist nicht das quit sondern die Schleife. Entweder musst du die Abbruchbedingung ändern (da nie NULL zurück kommt kann das also nicht die Bedingung zum Abbruch sein), oder die Schleife ist ganz einfach fehl am Platz.

Gruß
Sparrow


----------



## kniffel (5. Mai 2009)

Jap hab ich
Ich könnte es derzeit alternativ lösen wenn ich ihn abfragen lasse, ob die antwort dem String "OK" entspricht und er dann die Schleife verlassen soll.

Danke für die Hilfe, hat mich um einiges weitergebracht.


----------



## sparrow (5. Mai 2009)

Schreib für das Login eine eigene Methode die sich für dich entsprechend einloggt.
Da kannst du gleich ein bissl das Aufteilen üben 
Zurückgeben müsste dir die Methode die Möglichkeit zu kommunizieren (du hast ja die Streams schon kennen gelernt).
Innerhalb der Methode kannst du dann ohne Schleife vorgehen, denn in der Regel hat jede einzelne Zeile des Servers eine Bedeutung.
Bei TS bin ich mir nicht sicher, aber:

*[TS]* Damit wird der Server wohl sagen "Hallo ich bin ein TS-Server, rede mit mir.
*8767* Keine Ahnung was das heisst
*OK* Login erfolgreich

Was machst du wenn du dich mit dem Port vertust und dich nicht zum TS-Server verbindest? Du solltest also prüfen ob da wirklich ein [TS] zurück kommt. Sonst übermittelt du die Login-Daten vielleicht an ein ganz falsches Programm.
Was sendet der Server statt OK wenn du einen falchen Benutzernamen eingibst? Auch auf das nicht vorhandene OK musst du also reagieren.

Dir bleibt nicht viel anderes über als die Zeilen der Antwort sequenziell durchzugehen und auf ihre Richtigkeit zu prüfen. Dafür ist so ein Protokoll ja da.

Gruß
Sparrow


----------



## kniffel (5. Mai 2009)

Ich habe jetzt also die Methode für den login gemacht.

```
private static void login() {
      ...
      antwort = br.readLine();
      System.out.println(antwort+"     Hallo ich bin ein TS-Server");
      anfrage = "sel 8767";
      bw.write(anfrage);
      bw.newLine();
      bw.flush();
      antwort = br.readLine();
      System.out.println(antwort+"     Du hast 8767 Port ausgewählt");
      anfrage = "login admin ***";
      bw.write(anfrage);
      bw.newLine();
      bw.flush();
      antwort = br.readLine();
      System.out.println(antwort+"     Erfolgreich eingeloggt!");
      bw.close();
      br.close();
      echoSocket.close();
}//Ende try
      ...
}//Ende login
```

Er loggt sich ein, und ich bekomme die Antworten is System.out, aber ich kann sie aus dieser Methode nicht in die "Console" laden, also tf.append(antwort);
Außerdem hatte ich das alles vorher im actionPerformed eines Buttons.


```
//actionPerformed
public void actionPerformed(ActionEvent ae) {
       Object obj=ae.getSource();
...
//Command Button
       if (obj==cbut) {
             tf.setText("");
             //String usercommand = eingfe.getText()+"\n";
             //tf.append(usercommand);
             //eingfe.setText("");
             //eingfe.requestFocus();
             login();
        }//Ende if
}//Ende actionPerformed
```

Habe versucht noch eine Methode für das "Senden" zu schreiben, aber das selbe, ich bekomme es ja nicht in tf hinein.
Müsste ich also nicht alles ins actionPerformed packen?
Die Abfragen, ob OK zurückgegeben wird, oder [TS] wollte ich erst später machen, wenn dieses "Gerüst" ersteinmal steht.
Was ich noch nicht erwähnt habe, sollte ja alles was in das textfeld (eingfe) eingegeben wird ausgelesen werden und dann geschickt werden...Über einen Button...


----------



## sparrow (5. Mai 2009)

Ich würde vorschlagen:

Schreib zuerst einmal den Unterbau. Also die entsprechenden Methoden.
Diese Methoden dann hinterher aus einer GUI heraus zu füttern und Statusmeldungen in ein Textfeld zu schreiben ist dann das kleinste Problem


----------



## kniffel (11. Mai 2009)

Danke war ein guter Ansatz mit dem "von neu beginnen"
Habe alles erstmal in die Grundzüge auseinander genommen und habe es rein für CLI gebaut.
Konnte aber dann erst mithilfe von Threads lösen, dass auch wirklich die Leitung zwischen Empfangen und Senden unter-/schieden/brochen wird.

Danke für die Hilfe.
Schöne Grüße,
KniFFeL


----------



## Dissi (12. Jul 2009)

Hätte noch eine Lösung zum Grundproblem


```
...
        Vector<String> temp = new Vector<String>();
        String anfrage = command;
        bw.write(anfrage);
        bw.newLine();
        bw.flush();
   

        boolean notEmpty = true;
        while(notEmpty){
          try{
            temp.add(br.readLine());
          }catch(java.net.SocketTimeoutException e){
              notEmpty = false;
          }

        }
       }
      return temp;
...
```

Wenn nichts mehr im Stream kommt gibts einen Timeout. Dazu musst du noch im Konstruktor den Timeout setzen

```
echoSocket.setSoTimeout(500);
```


----------



## Downlord (16. Jul 2009)

Hallo! Zwischenfrage; darf man sich das Tool mal irgendwo ansehen, machst' es open source?

greez


----------



## kniffel (6. Nov 2009)

Heyho,
sorry dass ich mein Thema nocheinmal herauskrame, aber ich wollte daran weiterarbeiten. Bin schon einen großen Schritt weitergelangt.

Wie schon am Anfang hab ich aber jetzt das Problem, eine Schleife zu erstellen, die mir ständig jede Zeile ausliest und sie ausgibt, solange die Antwort nicht "OK" ist. Hat jemand einen Vorschlag?
_while(antwort!="OK") {...} ???_

Hier der Code:

```
while(true) {

    antwort = br.readLine(); //Lese Antwort von Server

            if (antwort.equals("quit") || antwort.equals("Quit")) {        //spielt derzeit noch keine große Rolle
               clientSocket.close();
               break;
            }//Ende if

            else {
                 System.out.print("RECIEVED:"+antwort+"\n");  //Ausgabe der Antwort
            
                 anfrage = inFromUser.readLine();  //Eingabe des Users an Server schicken.
//**************
//*********Fix me later in GUI
//**************
                    if (anfrage.equals("")) {             //Wenn man einen Leeren Befehl sendet...
                       bw.println(" ");                      //wird der Befehl auf "Leerzeichen" geändert und geschickt,
                       //clientSocket.close();           //damit der Server nicht in einer
                                                                //Endlosschleife auf leere Befehle antwortet.
                       //break;                              //somit liefert er die Antwort "error".
                    }//Ende if
//**************
//*********Fix me later in GUI
//**************
         
                            else {
                                    if (anfrage.equals("shutdown")){
                                       clientSocket.close();
                                       break;
                                    }//Ende if
                                 bw.println(anfrage);
                            }//Ende else 2
                }//Ende else 1
         }//Ende while
```

@ Downlord, ja ich werde es zur Verfügung stellen, wenn ich es fertig geschrieben habe und es anständig läuft.


----------



## Downlord (7. Nov 2009)

Zunächst mal eine Vereinfachung:

[JAVA=5] if (antwort.equalsIgnoreCase("quit")) {[/code]

Und dann: Du hast doch die Lösung bereits?

anstatt while(true) verwendest du


```
while(!antwort.equals("OK")) {
 ...
}
```

oder wo liegt das Problem?


----------



## kniffel (7. Nov 2009)

Das hatte ich versucht, aber ich komme zum Ergebnis, dass damit die While-Schleife verlassen wird und das Programm beendet wird.
Hier ein Auszug aus dem Ergebnis:

```
RECIEVED:[TS]        //Erste Antwort vom Server ohne einen Befehl geschickt zu haben
sl                          //Eingegebener Befehl
RECIEVED:8767       //Die Antwort erstreckt sich über 2 Zeilen.

RECIEVED:OK


C:\Users\KniFFeL\Desktop\Teamspeak_Tool\TCP>Pause
Drücken Sie eine beliebige Taste . . .
```
Was ich nicht erreichen möchte, ist dass er aus der Schleife geht, sondern einfach alles hintereinander ausgibt ohne jedes mal ihm mit Enter die Antwort abzufragen...
Anders gesagt, ich denke der BufferedReader wird nicht komplett, sondern eben nur Zeilenweise ausgelesen.
So wäre es richtig:

```
[TS]      //Erste Antwort
sl          //Eingabe
8767     //Antwort Zeile1
OK        //Antwort Zeile 2
           //Nichts gesendet
sllp       //.....
error

sl
8767
OK
```


----------



## Downlord (7. Nov 2009)

dann etwa so:


```
while(true) {
  // Hier auf Eingabe warten
  while(antwort.equals("OK")) {
    
  }
}
```

Aber andere Frage: Willst Du dir das wirklich noch antun? Bald kommt TS3 (beta release ist angekündigt).


----------



## kniffel (8. Nov 2009)

Okay sooo, danke dir für die Hilfe, soweit funktioniert das Programm schon einmal.
habe jetzt noch eine andere Frage:


```
if (antwort.equals("error") || antwort.equals("ERROR, not logged in") || antwort.equals("ERROR, no server selected"))
```

wie kann ich das noch schöner Darstellen? Ich dachte eigentlich an etwas wie z.B in DOS, oder MySQL der Platzhalter *
Alles was mit err anfängt, soll somit eingebunden werden. Habe etwas gegoogelt bezüglich wildcards bzw platzhalter, aber fand nichts passendes. (Nur etwas wie: %s, das aber nicht funktioniert hat).

Also ich tue mir das einfach an, weil ich so einen Charakter habe. Man könnte es als sehr stur oder zielstrebig ansehen. Wenn ich etwas begonnen habe, "muss" ichs beenden. Außerdem macht mir das ganze viel Spaß.
Ja die Beta soll im Dezember anfangen, darauf warte ich schon eine Ewigkeit^^
Vielleicht lässt sich mein TS2 Tool auch einfach auf TS3 umschreiben


----------



## andre111 (8. Nov 2009)

```
if(antwort.startsWith("err"))
```


----------

