# Daten kommen anders an als gesendert ?!



## Eule (1. Jul 2009)

Guten Tag an alle hier

Ich habe einen ObjectOut-  und InputWriter, den ich so erstellt habe


```
outWrtr  = new ObjectOutputStream(new BufferedOutputStream(socket.getOutputStream()));
new ObjectInputStream(socket.getInputStream());
```


Das senden der Daten geschieht über eine Methode sendMessage()


```
public synchronized void sendMessage(LinkedList<Object> send) 
	throws NullPointerException, IOException {
		
		//look for every object the appropriate class
		for(int i=0; i < send.size() ; i++) {
			
			//if the to send object is a Short
			if(send.get(i) instanceof Short) {
				Short x = (Short)send.get(i);
				outWrtr.writeShort(x);
//				outWrtr.flush();
			}
			
			//if the to send Object is a String
			else if(send.get(i) instanceof String) {
				outWrtr.writeUTF((String)send.get(i));
//				outWrtr.flush();
			}
			
			//if the to send Object is an Integer
			else if(send.get(i) instanceof Integer) {
				outWrtr.writeInt((Integer)send.get(i));
//				outWrtr.flush();
			}
			
			//if the to send Object is a Boolean
			else if(send.get(i) instanceof Boolean) {
				outWrtr.writeBoolean((Boolean)send.get(i));
//				outWrtr.flush();
			}
		}
		outWrtr.flush();
		outWrtr.reset();
	}
```

Dort sollen die 4 verschiedenen Objekte gesendet werden und zwar in der Reihenfolge, wie sie in der Liste sind. Die 1. Frage ist: Darf ich das überhaupt machen? verschiedene schreiboperationen auf einen Stream setzen?

Auf der Gegenseite wird der Inputstream ebenfalls wie oben erstellt.

Wenn ich jetzt ein paar Daten drüber gesendet habe (jede Klasse mehrmals) dann sendet empfängt die Gegenstelle irgendwann Unsinn.
Also Beispiel wollte ich nur ein Short = 6 drüber senden und laut Debugger sendet er das auch ab. Auf der Empfängerseite kommt dann aber mit

```
short code = inRdr.readShort();
```
 der Wert 1536 raus. Das jedes Mal. Wie gesagt, am Anfang funktioniert das Senden prima.

Könnte mir jemand etwas Hilfestellung geben?

Danke schon mal

Eule


----------



## tuxedo (1. Jul 2009)

Was du nicht tun solltest:

* Auf einer Verbindung mehrere Streamtypen mischen
* In die eine Richtung Typ A und in die andere Richtung Typ B benutzen

Speziell der Object*Stream fährt intern ein eigenes, minimalistisches Protokoll, weswegen ihn man nicht mit anderen Streamtypen mischen sollte. 

Ich rate dir (wie vielen anderen auch) zu einem entsprechenden eigenen Protokoll, oder eben zu RMI/SIMON/andere vergleichbare Lösung.


----------



## Eule (1. Jul 2009)

Meinst du mit Streamtypen so was wie BufferedStream usw? Sry. Ich kann mich dort noch nicht so gut aus.
Ich habe jetzt einfach mal den BufferedStream entfernt. Aber der Fehler tritt trotzdem noch weiterhin auf.


----------



## tuxedo (1. Jul 2009)

Du kannst Streams ineinander verketten:

Empfangsrichtung: InputStream -> InputStreamReader -> BufferedInputStream
Senderichtung: OutputStream -> OutputStreamReader -> BufferedOutputStream

Was du halt nicht tun solltest ist auf Sende und/oder Empfangsrichtung z.B. einen Object*Stream zu benutzen und 5min später dann einen Data*Stream ...

Auch solltest du auf der Sende UND Empfangsrichtung die gleichen Typen benutzen. Also nicht beim Senden den PrintStreamWriter benutzen und beim Empfangen dann den ObjectInpuptStream...


Aber wie gesagt: Du solltest dir entweder ein Protokoll überlegen, oder eben etwas benutzen das dir die Kommunikation erleichtert und intern mit einem Protokoll arbeitet.

- Alex


----------



## Eule (1. Jul 2009)

ich kenne mich mit erstellen von Protokollen nicht so gut aus. Kannst du mir einen Link mit Literatur geben, wo ich mich etwas einarbeiten kann?


----------



## tuxedo (2. Jul 2009)

Sorry. Ich kenne kein Buch das sich mit dem erstellen von Protokollen beschäftigt. I.d.R. ist das auch nicht nötig wenn man erstmal "den Schubser in die richtige Richtung" bekommen hat.

Würde dir erstmal dazu raten den Data(Input/Output)Stream zu benutzen. Damit kannst du bequem Strings, primitive Datentypen und Objekte übers Netz schicken.

Dann geht's ran ans Protokoll. Eine einfache Protokollbasis könnte so aussehen:

[byte] Nachrichtentyp: Hiermit kannst du bis zu 256 verschiedene Nachrichtentypen codieren
[body der Nachricht]

So. du schickst also vor der eigentlichen Nachricht ein byte raus. Dieses Byte beschreibt dir quasi wie die nachkommende Nachricht aussieht. 

FÜr eine Textnachricht könnte das wie folgt aussehen:

[1]
["Hallo Welt"]

Du gehst also hin und sendest eine 1 als byte. Der Empfänger weiß dann: Oh, eine 1. Das ist eine Textnachricht. Ich muss nun einen String vom DataInputStream lesen.

Danach willst du vllt. eine Datei schicken. So eine Nachricht kodierst du dann meinetwegen mit 2 als byte. Der body der Nachricht ist dann z.B. so aufgebaut:

[String] Name der Datei
[long] Länge der Datei in bytes
[bytes der Datei]

Eine komplette Nachricht zum senden einer Datei würde dann z.B. so aussehen:

[2]
["c:/MeineDatei.ext"]
[4850]
[bytes der Datei]

Der Empfänger liest also als erstes wieder ein einzelnes byte und findet die "2". Damit weiß er: Es handelt sich hier um eine Datei. Mit diesem Wissen liest er einen String ein, welcher gemäß vorher spezifiziertem Body den Namen der Datei darstellt. Als nächstes liest er einen Long-Wert. Damit weiß er wie groß die Datei ist und wieviele bytes er lesen muss um a) die Datei komplett zu empfangen und b) wann die nächste Nachricht beginnt.

Natürlich ist das nur ein Weg wie man ein Protokoll aufbauen kann. Aber es ist ein recht gebräuchlicher Weg der einfach zu handhaben ist.

- Alex


----------



## Eule (5. Jul 2009)

Danke. Genau so hatte ich das bereits gemacht. Gut zu wissen, dass ich mit der Verfahrensweise nicht auf dem Holzweg bin.

Der Fehler lag wohl wo anders. Ich musste das Programm noch mal auf Bandbreite trimmen und haben andere Reader und Writer genommen und dann ging es.

Vielen Danke für die Hilfe


----------

