Bild empfangen über Socket

  • Antworten:70
Gelöschter Account
  • Forum-Beiträge: 2.492

02.03.2014, 13:13:04 via Website

Es lag glaub ich daran das ich noch close stehen hatte.
Jetzt habe ich flush aber weiß nicht wie ich an das count was du genannt hast kommen soll.
Soll ich die Anzahl in die datas mit rein schreiben oder erst die Anzahl senden und dann die datas senden?

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

02.03.2014, 13:16:56 via Website

beides in einem Byte Array ist schon in Ordnung.
Du musst das nur beim Lesen berücksichigen

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

02.03.2014, 13:42:32 via Website

Also irgendwas mache ich falsch. Mit dem flush will er nicht wirklich arbeiten.
Wenn ich mit dem Empfänger debugge zeigt er mir nämlich nicht mal an das eine Verbindung ankommt.
Beim Sender klappt beim debuggen aber alles und er versendet es auch so wie ich es will.
Wenn ich aber close benutze kommt auch etwas beim Empfänger an.
Das mit den Zahlen am Anfang vom Array habe ich jetzt erstmal so gelassen.

Sender
[code]String str = et.getText().toString();
byte[] datas = new byte[str.getBytes().length+3];
byte[] text = str.getBytes();
datas[0] = (byte) (text.length+2);//Länge wir angefügt
datas[1] = 88;
datas[2] = 123;
for(int i = 3; i < datas.length; i++){
datas[i] = text[i-3];
}
BufferedOutputStream os;
os = new BufferedOutputStream(socket.getOutputStream());
os.write(datas);
os.flush();[/code]

Empfänger
[code]stream = new BufferedInputStream(s.getInputStream());

final byte[] bytes = readFully(stream);
if(bytes[1] == 88 && bytes[2] == 123){
String st = null;
byte[] text = new byte[bytes.length-3];
for(int i = 0; i < bytes.length-3; i++){
text[i] = bytes[i+3];
}
st = new String(text);
mClientMsg = st;
myUpdateHandler.sendMessage(m);
}


public byte[] readFully(InputStream input) throws IOException
{
byte[] buffer2 = new byte[4096];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = input.read(buffer2)) != -1)
{
output.write(buffer2, 0, bytesRead);
}
output.flush();//Hiermit versuche ich an die Anzahl zu kommen

int count = output.toByteArray()[0];//Der Code von impjor um das byteArray mit der Länge des Textes zu bekommen
byte[] buffer = new byte[count];
for (int i = 0; i < count; i++) {
buffer[i] = (byte) input.read();
}
return buffer;
}[/code]

Edit: Beim debuggen hab ich jetzt herausgefunden das er beim Sender hier hängen bleibt:
1ByteArrayOutputStream output = new ByteArrayOutputStream();
2 while ((bytesRead = input.read(buffer2)) != -1)
3 {
4 output.write(buffer2, 0, bytesRead);
5 }
Den OutputStream baut er noch auf aber dann kommt er beim debuggen nicht weiter

— geändert am 02.03.2014, 14:11:16

Antworten
impjor
  • Forum-Beiträge: 1.793

02.03.2014, 14:27:44 via Website

Alles kursive kannst du weglassen.

[code]
public byte[] readFully(InputStream input) throws IOException
{
byte[] buffer2 = new byte[4096];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = input.read(buffer2)) != -1)
{
output.write(buffer2, 0, bytesRead);
}
output.flush();//Hiermit versuche ich an die Anzahl zu kommen

int count = (byte) input.read();
byte[] buffer = new byte[count];
for (int i = 0; i < count; i++) {
buffer[i] = (byte) input.read();
}
return buffer;
}[/code]

Dir ist aber klar, dass ein byte einen Wertebereich von -128 bis +127 hat? D.h. wenn der Text mal 128 Zeichen hat krachts.

LG

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

02.03.2014, 18:18:20 via App

Dann musst du mehrere Bytes für den Text nehmen.

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
impjor
  • Forum-Beiträge: 1.793

02.03.2014, 18:26:56 via App

Pascal P.
Dann musst du mehrere Bytes für den Text nehmen.
Für das Bild auch.
Sollte aber kein Problem darstellen. Sonst mal googlen wie man einen int in ein byte-array umwandelt und umgekehrt.

LG

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

03.03.2014, 09:54:39 via Website

1int count = (byte) input.read();
Das hatte ich schon probiert, aber dann sagt er mir: NegativeArraySizeException weil count = -1 ist

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

03.03.2014, 10:02:16 via Website

Ähm, weisst du überhaupt was dieser Befehl heißt...?
1int count = (byte) input.read();
Die Bytes werden gelesen ind sofort in einen Integer umgewandelt, das kann doch nicht funktionieren.
Außerdem musst du wissen wie viel Bytes am Anfang zur Beschreibung kommen.
Diese dann extra einlesen.
Und zum konvertreren von Bytes in int gibt's ne spezielle Funktion: einfach mal dannach googeln

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

03.03.2014, 10:04:59 via Website

Ja impjor hatte das das ja so geschrieben. Ich muss doch eigentlich nur an das erste byte kommen weil da die Anzahl drin steht.
Aber wie komme ich daran?

— geändert am 03.03.2014, 10:05:09

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

03.03.2014, 10:10:04 via Website

Du must ein Byte Array haben und dann musst du das erste element lesen zb.
1Byte erstesByte = byteArray[0];

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

03.03.2014, 11:13:48 via Website

Okay ich hab das jetzt so gemacht:
[code]public byte[] readFully(InputStream input) throws IOException
{
//Alles wird eingelesen
byte[] buffer2 = new byte[4096];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = input.read(buffer2)) != -1)
{
output.write(buffer2, 0, bytesRead);
}
output.flush();

//An erster Stelle steht die Anzahl der zu lesenden Bytes
int count = buffer2[0];

//neues Byte[] mit dieser Anzahl wird erstellt und die Bytes eingefügt. Das fertige Byte[] wird zurück gegeben
byte[] buffer = new byte[count];
for (int i = 0; i < count; i++) {
buffer[i] = buffer2[i+1];
}
return buffer;[/code]

Wenn ich wieder close() anstatt flush() verwende kann ich einmal senden, wenn ich flush() nehme kommt wieder nichts über und er bleibt hier hängen:
1while ((bytesRead = input.read(buffer2)) != -1)
2 {
3 output.write(buffer2, 0, bytesRead);
4 }
Beim debuggen: Wenn ich "Hi" schreibe ist bytesRead = 5 was ja auch stimmt (Anzahl + 2 Zahlen + 2 Buchstaben = 5);
im buffer2 sind auch die richtigen bytes drin. Und der oututstream output hat auch x{hi da stehen
Aber warum macht er dann nicht weiter?
Es scheint wirklich nur noch an der Zeile zu liegen, weil beim Bild senden auch die ersten 4 5 Bytes richtig eingelesen werden und dann macht er nicht mehr weiter.

— geändert am 03.03.2014, 13:08:20

Antworten
impjor
  • Forum-Beiträge: 1.793

03.03.2014, 13:13:06 via Website

Pascal P.
Ähm, weisst du überhaupt was dieser Befehl heißt...?
1int count = (byte) input.read();
Die Bytes werden gelesen ind sofort in einen Integer umgewandelt, das kann doch nicht funktionieren.
Da muss ich aber wiedersprechen. Was soll daran nicht funktionieren? Ein byte belegt genau ein byte Speicherplatz und stellt Zahlen zwischen -128 und +127 dar. ein Integer belegt vier byte und stellt Zahlen zwischen -2147483648 und +2147483647 dar. Was soll daran nicht funktionieren? (Das (byte) diente nur zur Verdeutlichung, dass kein die Funktion keinen int-Wert sondern ein byte zurückliefert.)

@TE: Du hast den Code dringelassen, der wartet bis der Stream geschlossen ist:
while ((bytesRead = input.read(buffer2)) != -1)
Solange lesen, bis er -1 zurück gibt = Stream geclosed.

Meine Lösung hab ich dir ja schon in meinem letzten Beitrag gepostet.

LG

— geändert am 03.03.2014, 13:14:25

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

03.03.2014, 13:42:36 via Website

Cool danke, beim Text versenden klappt jetzt alles so wie gewollt, aber beim Bild senden nicht.
Das byte[] wird wohl richtig erstellt dann mach ich das:
1final Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 2, bytes.length-2);
aber dann wird bmp ist null angezeigt.
Und wenn ich dann beim debuggen auf weiter drücke springt der immer zwichen dem count = (byte) input.read() und dem Bild erstellen/ImageView erstellen/Bild dem ImageView hinzufügen hin und her.

— geändert am 03.03.2014, 13:46:14

Antworten
impjor
  • Forum-Beiträge: 1.793

03.03.2014, 14:47:19 via Website

Ich denke mal dieser Fall ist eingetreten:

impjor

Dir ist aber klar, dass ein byte einen Wertebereich von -128 bis +127 hat? D.h. wenn der Text mal 128 Zeichen hat krachts.

Ein Bild hat wohl mehr als 127 Bytes. Du sendest in einem byte aber die Anzahl der zu lesenden Bytes. Da du nur ein byte benutzt kann dieses max. den Wert 127 annehmen. Du kannst also max. ein Bild mit der Größe von 127 Byte senden.
Lösung: Du musst mehrere Bytes nutzen, um die Anzahl der nachfolgenden Bytes anzugeben. Z.B. einen Integer (4 Bytes). D.h. du musst einen Integer (die Anzahl der Bytes aus denen ein Bild besteht) in vier bytes umrechnen und diese am Anfang senden. Wenn du ein Bild empfängst ließt du die ersten view bytes aus, wandelst sie wieder in einen integer um und dann weißt du, wie aus wievielen bytes das Bild besteht.

LG

Liebe Grüße impjor.

Für ein gutes Miteinander: Unsere Regeln
Apps für jeden Einsatzzweck
Stellt eure App vor!

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.03.2014, 09:45:44 via Website

Achso okay das könnte natürlich sein, aber wie lese ich denn dann nur die ersten vier bytes ein?
Hab das jetzt so versucht (in der readFully Methode):
[code]
byte[] längeInBytes = new byte[4];//Hier sollen die ersten vier bytes rein
for(int i = 0; i < 4; i++){
längeInBytes[i] = (byte) input.read();//Die ersten vier bytes werden gelesen...
}
ByteBuffer bb = ByteBuffer.wrap(längeInBytes);//...und in einen Integer umgewandelt
bb.order(ByteOrder.LITTLE_ENDIAN);
int count = bb.getInt();
[/code]

und den Rest dann so wie davor.
[code]
byte[] buffer = new byte[count];
for (int i = 0; i < count; i++) {
buffer[i] = (byte) input.read();
}
return buffer;
[/code]

Dann sagt er mir aber auch NegativeArraySizeExceptionn oder OutOfMemoryError

— geändert am 04.03.2014, 09:50:04

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

04.03.2014, 09:48:42 via App

Und funktioniert es so?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.03.2014, 09:50:21 via Website

Nein dann kommt NegativeArraySizeExceptionn oder OutOfMemoryError.

— geändert am 04.03.2014, 10:07:58

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

04.03.2014, 10:06:40 via Website

An welchen stellen denn?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.03.2014, 10:07:50 via Website

1byte[] buffer = new byte[count];
Wenn er das versucht.

Das längeInBytes Array hat dann folgenden Inhalt:
[0] = 0
[1] = 0
[2] = 51
[3]= 95
Klingt das realistisch?
Und count ist dann: 1597177856

— geändert am 04.03.2014, 10:08:07

Antworten
Pascal P.
  • Admin
  • Forum-Beiträge: 11.286

04.03.2014, 10:10:34 via Website

Das Count ist viel zu hoch, so ein großes ByteArray kannst du garnicht erstellen.
Ich glaube dort liegt der Fehler.
Wieso ist Count so eine Große Zahl?

LG Pascal //It's not a bug, it's a feature. :) ;)

Antworten
Gelöschter Account
  • Forum-Beiträge: 2.492

04.03.2014, 10:20:33 via Website

Beim Sender war jetzt grad die länge: 14575
Dann hab ich das so (hab ich im Internet gefunden) in ein byte[] umgewandelt:
1byte[] längeInBytes = ByteBuffer.allocate(4).putInt(länge).array();
Das byte[] kommt da raus:
0
0
56
-17

Edit: Hab jetzt in den code da oben noch .order(ByteOrder.Little_Endian) eingefügt, dann ist beim Empfänger count auch ungefähr in dem Bereich also wahrscheinlich jetzt richtig.
ABER: Wenn ich dann weiter debugge beim Empfänger bleibt er hier irgendwo hängen (Beim Bilder versenden verwende ich auch flush():
[code]
for (int i = 0; i < count; i++) {
buffer[i] = (byte) input.read();
}
[/code]
Hinweis: Beim Text versenden klappt das alles, also die ersten vier bytes auslesen in int konvertieren neues array erstellen und so weiter

Komisch, auf einmal funktionierts ich weiß nicht was ich geändert hab. Danke euch beiden habt mir sehr geholfen :)

— geändert am 04.03.2014, 11:43:52

Antworten