# TCP "verlorene Pakete"



## hdw (4. Aug 2009)

Hallo,

vorweg, ich bin neu in Java.

Ich hab im Forum nichts gefunden, wie ich vermeiden kann, dass ich TCP-Nachrichten in meiner Anwendung übersehe. 
Klar, in TCP sollte eigentl. nichts verloren gehen, daher vermute ich, der Fehler liegt in meiner Anwedung/Netzwerkaufruf.

Kurz zum Prgramm:
Ich lese vom Heim-Netzwerk von einem anderen PC die an mich geschickten Nachrichten (TCP). Auf den "Sender" der Daten habe ich keine Einfluss.
Die Nachrichten sind kurze Strings, wenige hundert Bytes.
Die Nachrichten, die ich bekomme sind inkrementell, d.h. in jeder Message wird nicht alles uebertragen, sondern nur Differenzen zu den vorangegangenen Werten. Daher darf nichts übersehen werden. Es gibt keine Paketnummern.
Die Netzwerk-Kommunikation erfolgt in einem eigenen Thread, losgeloest v. der eigentl. Anwendung.
Die Leseroutine (s.u.) ist in einer Endlosschleife ohne sleep() eingebettet. 

Der Socket ist mit SoTimeout erzeugt:

```
...
SocketAddress socketAddr 
   = new InetSocketAddress( nameOrAddress, port );
socket = new Socket();
socket.connect(socketAddr, 1000);  // allow time to connect
// socket = new Socket(nameOrAddress, port);
socket.setSoTimeout(1100); // set socket read timeout
...
inStream    = sock.getInputStream();
outStream   = sock.getOutputStream();
...
```

Nun habe ich den Verdacht, dass manchmal in (sehr) kurzer Folge 2-3 Nachrichten hintereinander kommen, ich aber nur jew. das letzte in meiner Anwedung lese.
In der Ausgabe des LOGGERs kann ich nachvollziehen, dass manchmal Nachrichten fehlen.
Aber wie komme ich an die fehlenden/übersehenen/verlorenen Nachrichten? 
Ich kann leider nicht mal mit Sicherheit behaupten, dass sie überhaupt gesendet wurden ???:L

Aber wie stelle ich sicher, dass ich keine Nachricht übersehe und wie komme ich an die ggf. "übersehenen" Pakete? Hat eine(r) von Euch 'ne Idee?

Hier meine Leseroutine Code in Auszügen.


```
private String readMessage () {
    String dataLine = "";
    try {
      BufferedReader in = new BufferedReader(new InputStreamReader(inStream));
      dataLine = in.readLine();              // blocking read ...
      dataTime = System.currentTimeMillis(); // ... add data time stamp
      if (LOGGER.isTraceEnabled()) {
        LOGGER.trace("readLine(): " + dataLine);
      }
    }
    catch (SocketTimeoutException ste) {
      /* read timed out -> application paused ... */
      LOGGER.trace("SocketTimeoutException from readline(): "+ste.toString());
    }
    catch (IOException ioe) {
      /* read problem */
      LOGGER.warn("IOException from readLine(): "+ioe.toString());
      // FIXME: close socket, inStream, outStream
    }
    finally {
      // FIXME: close logfile
    }
    return dataLine; // return message or empty string
  } /* end readMessage */
```

Ist meine Implementierung schon im Ansatz falsch?
Wie müsste ich den Code umschreiben, damit ich keine Nachrichten übersehe/überspringe. 

Danke und Gruss, Holger


----------



## sparrow (4. Aug 2009)

Wie sieht der Codeteil aus der den ServerSocket erstellt?


----------



## hdw (4. Aug 2009)

Tja, wenn ich das wüsste...
Der Server (ich vermute Du meinst den Sender) ist ein binäres Programm, ein echtes *.exe. 
Sonst haette ich da schon mal reingeschaut oder gar "nachprogrammiert", um zu sehen was tatsächlich gesendet wird.


----------



## sparrow (4. Aug 2009)

Momemt.... 
also erstmal: TCP-Pakete müssen nicht nummeriert werden. Das Protokoll sorgt dafür dass alles und in der richtigen Reihenfolge in der Anwendung ankommt.

Du nimmst also Verbindung mit einem fremden Rechner auf.
Vorweg stellt sich also die Frage: Wer "lauscht" auf einen Port um die Verbindung anzunehmen? Dein PC oder der fremde PC?


----------



## hdw (4. Aug 2009)

Bzgl. Nummerierung: 
Ich meinte hier nur eine anwendungsspezief. Nummerierung der Nachrichten durch den Sender. 
Das Fehlen einzelner Nchtichten war zunächst nur anhand des Zeitstempels der Nachrichten zu erkennen, denn es gibt Nachrichten, die ca. alle 200ms gesendet werden und eine andere Nachrichtenkategorie sollte ca. alle 1000ms kommen. Da die Nachrichten eine kontinuierl. Bewegung beschreiben, sind die Ausfälle dann auch anhand der Nachrichteninhalte erkennbar.

Der andere PC (ich nenne ihn mal Sender) lauscht auf einem Port und erwartet, dass eine Anwendung eine Verbindung mit ihm erstellt und dort anmeldet. Der Verbindungsaufbau funktioniert problemlos. Ich sehe beim Sender im GUI auch, dass mein Programm (der Empfänger) korrekt erkannt wurde und angemeldet ist.

Meine Java-Programm ist der Empfänger, weil er nach dem Verbindungsaufbau nur noch Daten empfängt, aber nichts sendet (ausser einer initialen Anmeldungsnachricht, die vom Sender bestätigt wird). 
Danach beginnt der Sender seine Nachrichten an den Empfänger zu senden.

Aus dem was ich bisher weiss, sollte der "Sender" der Server sein, meine Anwendung muesste daher der Client sein.


----------



## faetzminator (5. Aug 2009)

Versuch mal deinen [c]BufferedReader[/c] zu behalten, und von diesem jeweils ein readLine() aufzurufen, statt immer einen neuen zu erstellen.


----------



## HoaX (5. Aug 2009)

faetzminator hat gesagt.:


> Versuch mal deinen [c]BufferedReader[/c] zu behalten, und von diesem jeweils ein readLine() aufzurufen, statt immer einen neuen zu erstellen.



Da tippe ich auch drauf. Der BufferedReader tut nämlich das was er soll, er puffert/liest Daten auch wenn du sie noch nicht abrufst. Wenn du beim nächsten Aufruf deiner Methode wieder einen neuen erstellst dann verwirfst du damit die bisher gepufferten.
Wenn das Protokoll wirklich auf Strings basiert dann erstelle _einmal_ den BufferedReader. (Und ich würde beim InputStreamReader noch fest das Encoding mit angeben!).


----------



## hdw (5. Aug 2009)

Danke für die Tipps. Ich werd es ausprobieren.
Wird aber wohl 2 Wochen dauern, bis ich wieder weiter machen kann... hab nun Urlaub  
Bis spaeter wieder!


----------



## hdw (14. Aug 2009)

Treffer, Eure Tipps waren richtig.
Natürlich war die Ursache das laufende Instanziieren eines neuen BufferedReader.  Peinlicher Fehler  
Danke!


----------

