IO-Klassen nicht synchron?

JavaJoe

Mitglied
Hallo!
Ich arbeite zur Zeit an einer kleinen Server-Client Anwendung. Der Server ist hierbei in der Lage auf verschiedene Kommandos, welche in String firm übermittelt wrden zu reagieren.
Es tritt hierbei jedoch ein Problem auf welches ich absolut nicht nachvollziehen kann.
Im Clienten laufen zwei Threads welche unabhängig voneinander in einer 3ten Klasse die Methode

Code:
public synchronized void Send(String com)
 {

  System.out.println("Sende : "+ com);
  try
  {
   this.out.write(com.getBytes());
   this.out.flush();
  }catch(Exception x)
  {
   System.out.println("Senden fehlgeschlagen!");
  }
  System.out.println("habe gesendet: "+com);

 }



aufrufen.

Wenn nun die 2 Threads diese Methode schnell hintereinander aufrufen empängt der Server die Kommandos nicht einzelnd sondern als einen zusammenhängenden String.
Der Server arbeitet so:

Code:
public synchronized void run()
 {
   String second="";
   String third="";
   String vier = "";

  while(true)
  {

    byte[] input = new byte[1000];
    second="";
    third="";
    vier = "";

    try
    {

     this.in.read(input);

    }
    catch(Exception y)
    {

    }





    String inputs =  this.bearbeitearray(input);
    input=null;
    System.out.println("Input:      "+inputs);
    tok =  new StringTokenizer(inputs);
    String first = tok.nextToken();

    if(tok.hasMoreTokens()){

     second = tok.nextToken();
     System.out.println("Second: "+ second);
    }
    if(tok.hasMoreTokens()){

     third = tok.nextToken();
     System.out.println("third: "+ third);
    }

    if(tok.hasMoreTokens()){

      vier = tok.nextToken();
      System.out.println("Vier: "+ vier);
    }
    tok=null;



Da alle IO Klassen, korigiert mich wenn ich falsch liege, synchronisiert sind kann ich mir diesen Fehler nicht erklären.

Bsp.:
Es wird gesendet: "COMM IMG"
direkt danach: "COMM MOUSEMOVE 52 57"
der Server empfängt: "COMM IMGCOMM MOUSEMOVE 52 57"
worauf er natürlich eine Fehlermeldung bringt.

Vielen Dank im Vorraus.
MFG
 
Synchronisiert bedeutet meiner Meinung nach nur, dass die Methoden nicht mehrfach gleichzeitig ausgeführt werden können. Es spricht also nichts dagegen z.B. die Send-Methode sehr schnell hintereinander auszuführen, so dass zwar die einzelnen Befehle nicht zerpflückt/gemischt werden, aber halt hintereinander gehangen - es landet ja alles im gleichen Stream wenn ich das richtig gesehen hab und wenn die Lese-Operation zu spät kommt ... naja, dann tritt halt dein Fehler auf.

Abhilfe könntest du schaffen, wenn du irgendein Zeichen mit einbaust um kenntlich zu machen, dass der Befehl an der Stelle beendet ist. Also beim Senden zum Beispiel immer mit \n die einzelnen Befehle abschließt.

Eine andere Möglichkeit wäre in der Send-Methode zu warten bis der Server die Anfrage verarbeitet hat und z.B. ein "ok" zurückschickt.
 
Vielen dank für die Antwort! Ich dachte n die IO klassen wären so aufeinander abgestimmt, dass ein Outputstream erst dann wieder freigegeben wird wenn der Inputstream die gesendeten Daten eingelesen hat. Denn ruft man die write() methode eines Outputstreams auf passiert solange nichts bis ein inputstream read() aufruft.
Aber nicht desdo trotz werde ich jetzt mal deine vorschläge umsetzen.

MFG
Joe
 
Hmm, falls du damit recht hast, nützen meine Vorschläge vielleicht nichts. Ich weiß zwar, dass der InputStream wartet bis Zeichen gelesen wurden (wobei hier letztens auch das Problem diskutiert wurde, dass er genau das nicht getan hat und stattdessen (weil der Inputstream leer war) null zurückgegeben wurde), aber ich dachte bisher, dass man in den OutputStream beliebig viel packen kann (naja, nicht beliebig, irgendwann ist er ja voll, aber halt mehrfach hintereinander Sachen...), ohne dass da blockiert wird. Hängt vielleicht auch von der Art der verwendeten Streams ab, gibt ja zig Klassen.

Naja, aber eine andere Idee woran es noch liegen könnte hab ich da auch nicht. Es kann ja praktisch nur so sein, dass zweimal hintereinander in den gleichen Stream geschrieben wird, sonst könnte dein Fehler ja gar nicht erst auftreten.

Aber ob Streams jetzt blockierend sind oder nicht - mit dem Endzeichen für Befehle löst du dein Problem ja auf jeden Fall. Auch wenn's vermutlich schönere Möglichkeiten gibt.
 
Also ich versteh das auch nicht! Ja mit dem ende Zeichen wäre es auf jeden fall gelöst nur da würde mir dann immer der letzte befehl verloren gehen oder nicht?
Nunja ich fand die idee mit dem OK senden ganz gut nur ahb ich mir gedacht liest der Client von einer Zentralen Klasse aus ein. Wie soll ich dann einem Thread der in der Lesen Methode steckt bescheid geben, dass das Ok eingegangen ist? ich könnte eine variable belegen, diese müsste cih jedoch laufend mit einer Schleife abfragen! Ich ahbe schon an wait() und notify gedacht. Eigentlich die top lösung wenn wait nicht den Monitor freigeben würde.....
Vielleicht könne auch noch andere was dazu sagen.
MFG
Joe
 
Zurück