# InputStream and ObjectInputStream zur gleichen Zeit



## mabuhay (10. Jul 2010)

Hallo

Ich habe eine Frage betreffend dem Senden von Bildern. Mein aufbau ist folgender:

Ich habe einen Server und einen Client. Diese kommunizieren mit InputStream und OutputStream. Nun möchte ich manchmal ein Bild übertragen (.jpg), also dachte ich ich kann einfach einen ObjectOutputSTream beim Client und einen ObjectInputStream beim Server öffnen, das Bild byteweise in den ObjectOutputStream schreiben und lese es dann aus dem ObjectInputStream.

Das Problem ist nun dass die Bilddaten beim Server auch im InputStream ankommen (ich sehe einfach komische Zeichen da ich die empfangenen zeichen am stdio ausgebe), aber den InputStream möchte ich nur für die kommunikation (befehle etc) verwenden. Ich habe es nun so gemacht dass der InputStream nicht ausgelesen wird, während ein Bildtransfer aktiv ist.

Meine Frage ist nun, ob es ein Problem ist den InputStream und den ObjectInputStream offen zu haben. Der Transfer endet einfach nie. Die Bilder sind zwischen 200KB und 400KB gross.

So sende ich das Bild:

```
FileInputStream fis = new FileInputStream(imagepath);
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
ObjectOutputStream oos = new ObjectOutputStream(client.getSocket().getOutputStream()) ;
oos.writeObject(buffer);
oos.close();
```

So empfange ich das Bild:

```
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
byte[] buffer = (byte[])ois.readObject();
ois.close();
FileOutputStream fos = new FileOutputStream("filename.jpg");
fos.write(buffer);
fos.close();
```

Senden und Empfangen kommt nie zum ende. Gibt es eine Möglichkeit, den stand der übertragung zu sehen?

Wenn benötigt, kann ich weiter Infos posten.

[EDIT]
Ich habe gerade herausgefunden dass es hier hängt:

```
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
```
Ist es möglich dass es nicht möglich ist den ObjectOutputStream zu öffnen weil schon der InputStream offen ist? Das komische ist dass es erst eine Exception gibt wenn ich einen zweiten Client welcher mit dem Server verbunden ist trenne...
Wie auch immer, muss ich eine separate Verbindung aufbauen um das Bild zu übertragen?

mfg


----------



## SlaterB (11. Jul 2010)

also ich kann nur dringend dazu raten, keinen ObjectInputStream darüber zu setzen, noch irgendwo irgendwann je Streams zu wechseln,
gerade für bytes lohnt sich das in diesem Fall doch auch überhaupt nicht,

bleibe bei normalen Stream und überlege dir ein Protokoll,
wenn du jetzt schon weißt, wo du new ObjectInputStream() schreiben würdest, dann weist du auch, wo das byte[] im normalen Stream kommt,
dann brauchst du nur noch die Länge, die vorher reinschreiben, richtig auslesen und passend viele bytes aus dem normalen InputStream lesen, fertig


----------



## mabuhay (11. Jul 2010)

Vielen Dank für die Antwort

Habe es nun so gemacht und funktioniert irgendwie auch, aber noch nicht so ganz.
Also als erstes schickt der Client einen String mit der Dateigrösse und dann einer zur Indikation dass der Bildtransfer anfängt. Von da an kopiert der Server alle empfangenen bytes in einen lokalen Puffer (wird jeweils aufgerufen wenn Daten im InputStream sind):

```
System.arraycopy(recmsg.getBytes(), 0, imageBuffer, imageBufferPos, recmsg.getBytes().length);
imageBufferPos += recmsg.getBytes().length;
```
Das Problem ist nun dass der Client irgendwie viel zu viele Daten sendet. Der Client sendet folgendermassen (natürlich mit try/catch etc)

```
System.out.println("Loading image");
FileInputStream fis = new FileInputStream(path);
buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
System.out.println("Sending image");
client.getSocket().getOutputStream().write(buffer);
System.out.println("Sending done");
```
Die Grösse von "buffer" ist ok, habs mit der Angabe im Dateisystem verglichen.

Der Server liest nun also solange den InputStream aus wie Daten kommen. Bei einer Dateigrösse von z.B. 357214 Bytes empfange ich aber 1357214 Bytes.
Des weiteren sind die Bilder nicht anzeigbar. Fehlermeldung "Fehler beim Lesen einer JPEG-Bilddatei (Not a JPEG file: starts with 0xef 0xbf)"

Blicke da nicht ganz durch was hier falsch geht. Hab mal das senden mit

```
c.getSocket().getOutputStream().write(buffer, 0, 10000);
```
getestet. Dabei empfange ich aber 17927 Bytes.

Hilfeeee


----------



## SlaterB (11. Jul 2010)

> Bei einer Dateigrösse von z.B. 357214 Bytes empfange ich aber 1357214 Bytes.

stolzer Versuch, wie wärs erstmal damit EIN EINZELNES byte 17 erfolgreich zu versenden  ,
auch nicht aus einer Datei, sondern das darf sich das Programm ruhig im Quellcode erdenken,

warum bei dir irgendwas grad oder schon immer nicht geht, kann ich aktuell nicht sagen, vielleicht google-Beispiel zu 'bytes per Sockets übertragen' ausprobieren,
hast du eigentlich schon je irgendwas erfolgreich versendet? kaum vorzustellen dass die Datei das erste ist,
wie war das mit der Länge des Arrays vor dem Array?
was immer ging, was war denn das, wie wurde dort gesendet, empfangen, was ist anders?

generell eine Möglichkeit ist, auf Sender und Empfänder Reader und Writer statt Streams einzusetzen, also Zeichen/ Text/ Strings zu versenden,
wenn ein 'a' erfolgreich bei der Gegenseite ankommt und dann wahrscheinlich auch alle anderen einfachen Buchstaben + Ziffern (Umlaute schon zu kompliziert), dann kann man damit jede beliebige Info aufbauen,

z.B. Base64-Encoding für die bytes
Base64 - Wikipedia, the free encyclopedia


und wieder gilt: nur eine Art Stream bzw. höheres,
wenn du einen BufferedWriter beim Client verwendest, der in den OutputStream schreibt,
dann weder vor der Erstellung des BufferedWriter, noch während dessen Verwendung noch später danach auf irgendeine andere Weise mit dem OutputStream agieren, sondern dann immer nur mit dem BufferedWriter, 
auch close() ganz am Ende auf den BufferedWriter usw.


----------



## mabuhay (11. Jul 2010)

Also ich habe einen Server und einen Client, welche sich erfolgreich verbinden und auch die Kommunikation klappt ohne Probleme wenn ich Strings versende.

Nun habe ich den OutputStream vom Client genommen und Schreibe die Bytes des Bildes dort hinein. Habs gerade noch mit Text versucht:

```
c.getSocket().getOutputStream().write("testtesttest".getBytes());
```
und das kommt ohne Probleme und korrekt an, keine weiteren ungewünschten Bytes oder so. Auch mit 2400 Bytes (ein String mit vielen "testtesttest...") läuft ohne Probleme.

Nun zu dem Base64 encoding...
Heisst das, dass Input- und OutputStream nur für Text gedacht ist? Ich habe mir gedacht dass das keine Rolle spielt, und ob jetzt ein Byte reinkommt oder ein Buchstabe (welcher ja auch durch ein Byte/Bytes dargestellt wird), wenn ich im OutpuStream alles wieder richtig zusammensetze funktionierts.

Also noch ein Test:

```
buffer = new byte[5];
buffer[0] = 'A';
buffer[1] = 18;
buffer[2] = 19;
buffer[3] = 20;
buffer[4] = 'X';
```
Das kommt nur an wenn Buchstaben drin sind... und jetzt weiss ich evtl auch was falsch gehen könnte. Mein Server liest die Bytes und konvertiert es in einen String, da könnte natürlich schon mal was verloren gehen...
werde das mal umbauen.


----------



## Wildcard (12. Jul 2010)

Für die Art von Protokol zu entwickeln kann ich dir wärmstens Net4J empfehlen. Das nimmt der den Großteil der Low-Level Aufgaben ab.
Net4j - Eclipsepedia


----------



## mabuhay (14. Jul 2010)

Wildcard hat gesagt.:


> Für die Art von Protokol zu entwickeln kann ich dir wärmstens Net4J empfehlen. Das nimmt der den Großteil der Low-Level Aufgaben ab.
> Net4j - Eclipsepedia



Danke, das tönt ja schon mal gut... nur, gibt es auch irgendwelche Dokumentation oder Beispiele dazu ausser dem JavaDoc? Habe deine Seite und Welcome to Net4j gefunden, aber beide Seiten sind irgendwie nicht so sehr hilfreich.

mfg


----------



## Wildcard (14. Jul 2010)

Dokumentation ist leider absolute Mangelware. Das heißt allerdings nicht dass das Projekt nicht 'mature' wäre. Net4J bildet die Kommunikationsschicht für CDO welches produktiv in der Industrie in wirklich großen Projekten eingesetzt wird (auch von der NASA und anderen großen Namen).
Glücklicherweise ist die Sache so einfach das die Beispielprojekte im Prinzip genügen um in ein paar Minuten sein erstes Protokoll umzusetzen.
Wenn ich mich richtig erinnere liegen die examples im Eclipse Modelling CVS.
Die Beispielprojekte beeinhalten ein Echo Protocol (Hello World artig), ein Filetransfer protocol und einen Chatserver inklusive Client.


----------



## mabuhay (1. Aug 2010)

Ich habs jetzt mal so gelöst wie anfangs Beschrieben. Hatte noch ein paar Probleme zu lösen, funktioniert jetzt aber ganz gut.
1. habe ich eine separate Verbindung um die Bilder zu senden
2. habe ich gemeint, dass in.read(b) wartet bis die Anzahl Bytes der grösse von b empfangen wurden. Dem ist aber nicht so, sondern ich muss mit dem rückgabewert von in.read(b) schauen wie viele Bytes empfangen wurden und in einer Schlaufe wiederholt auslesen und in den Bildpuffer schreiben

mfg


----------



## mabuhay (14. Sep 2010)

Noch mal kurz das Thema geöffnet ^^

Ich habe Net4j nun hier gefunden: Eclipse Modeling - EMF - Home
JavaDoc ist hier: Net4j Javadoc

Installiert habe ich es über das Eclipse-Install-Tool (Help->Install new Software), dort bei "Work with" habe ich "--All available Sites--" ausgewählt und dann Net4j in der Tabelle unter "Modeling" gefunden

Wie verwende ich das jetzt in einem Projekt und wo finde ich die Beispiele? (beim installieren hats geheissen das Beispiele dabei sind). Im Java Build Path sehe ich nur die JRE System Library und meine eigenen. Net4j ist (ich verwende Ubuntu) unter USER/.eclipse/org.eclipse.platform.../plugins installiert, also es hat dort viele org.eclipse.net4j... jar's.
@Wildcard: hast du mir evtl ein kleines Beispiel zum Start? Sogar im JavaDoc gibt es so gut wie keine Beschreibungen...

mfg


----------



## Wildcard (14. Sep 2010)

Die Examples liegen im CVS. [Modeling_Project] Eclipse Source Repositoriesorg.eclipse.emf/org.eclipse.emf.cdo/plugins
Fang am besten mit dem Net4J Examples Projekt an. Für ein größeres Beispiel kannst du dir die Buddies Plugins auschecken (ein Chat Protokoll).


----------



## mabuhay (14. Sep 2010)

Oooh, vielen Dank


----------

