ByteArray über Netzwerk senden klappt nicht

Klösp

Aktives Mitglied
Hallo Java-Forum.

Ich möchte ein Objekt in ein Byte[] speichern und dann an den Server schicken.


Java:
import java.io.Serializable;

public class Person implements Serializable {
	
	private String name, vorname;
	private int alter;
	
	public Person(String name, String vorname, int alter) {
		super();
		this.name = name;
		this.vorname = vorname;
		this.alter = alter;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", vorname=" + vorname + ", alter="
				+ alter + "]";
	}

}


Client:
Java:
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.net.Socket;


public class Client {

	public static void main(String[] args) throws IOException {

		Socket server = null;

		try {
			server = new Socket("localhost", 8080);
			Person p = new Person("Gause", "Gundula", 42);
			ByteArrayOutputStream baos=new ByteArrayOutputStream();
			ObjectOutputStream os = new ObjectOutputStream(baos);
			os.writeObject(p);
			os.flush();
			byte[] ba=baos.toByteArray();
			baos.close();
			
			ObjectOutputStream oss = new ObjectOutputStream(server.getOutputStream());
			oss.write(ba);
			oss.flush();
			
			BufferedReader br=new BufferedReader(new InputStreamReader(server.getInputStream()));
			System.out.println(br.readLine());			
		} finally {
			if (server != null) {
				server.close();
				
			}
		}
	}
}

Server:
Java:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
 
public class Server {
 
    public static void main(String[] args) throws IOException {
 
        ServerSocket server = new ServerSocket(8080);
 
        while (true) {
            Socket client = null;
            try {
                client = server.accept();
                System.out.println("verbindung aufgebaut");
                doSomething(client);
 
            } finally {
                if (client != null) {
                    try {
                        client.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
 
    private static void doSomething(Socket client) throws IOException {
 
     InputStream is=client.getInputStream();
     
     PrintWriter pw=new PrintWriter(client.getOutputStream());
     byte[] pb=new byte[1024];
     int i;
    try {

    	while((i=is.read(pb))!=-1){
    		System.out.println("Write "+i+" Bytes.");
    	}
    	 ByteArrayInputStream bis = new ByteArrayInputStream (pb);
         ObjectInputStream ois = new ObjectInputStream (bis);
         Person p= (Person) ois.readObject();
         
		System.out.println(p.toString());
		pw.write("Erfolg \n");
		pw.flush();
		
	} catch (ClassNotFoundException e) {
	
		e.printStackTrace();
	}
    finally{
    	is.close();
    	pw.close();
    }
        
    }
}

Irgendwo hängt es noch.

Beim Server bekomme ich folgenden Ausgabe:
verbindung aufgebaut
Write 4 Bytes.
Write 112 Bytes.

Also wird ja scheinbar etwas übertragen und auch ins Byte[] geschrieben.
Das Problem ist denke ich dann bei zurück wandeln in ein Object.

Kann jemand helfen?

Danke im Vorraus
 
K

kneitzel

Gast
Hi,

ich denke, dass der eigentliche Fehler hier liegt:
while((i=is.read(pb))!=-1)

is.read(pb) liest in das bytearray pb und zwar immer von Anfang an. Da die Daten des Servers nach und nach ankommen (Du hast ja mehrere Zeilen mit dem Write...), überschreibst Du die Daten immer selbst. Das wäre zu fixen über eine Erfassung der aktuellen Position und der Nutzung der read Datei, die auch die Position (Offset) und Länger (also Länge Array - Position) mitnimmt.

Aber das ist alles meiner Meinung nach so gar nicht notwendig. Du kannst den ObjectStream doch immer direkt auf den Stream vom Socket setzen. Oder habe ich da etwas verpasst, das eben dies verhindert?

Mit den besten Grüßen,

Konrad
 
K

kneitzel

Gast
Wie der Code aussehen könnte habe ich jetzt einmal schnell für Dich ausprobiert. Dies wird mein erstes Posten von Code, daher bitte Geduld haben, falls es nicht gleich ganz so von Anfang an klappen sollte. (Und um es kurz zu halten habe ich nur die main Funktion vom Client und die doSomething Funktion vom Server kopiert.)

Client - main:
Java:
        public static void main(String[] args) throws IOException {

            Socket server = null;

            try {
                server = new Socket("localhost", 8080);
                Person p = new Person("Gause", "Gundula", 42);
                ObjectOutputStream os = new ObjectOutputStream(server.getOutputStream());
                os.writeObject(p);
                os.flush();
                BufferedReader br=new BufferedReader(new InputStreamReader(server.getInputStream()));
                System.out.println(br.readLine());
            } finally {
                if (server != null) {
                    server.close();

                }
            }
        }

Server-doSomething:
Java:
        private static void doSomething(Socket client) throws IOException {
    
         InputStream is=client.getInputStream();
    
         PrintWriter pw=new PrintWriter(client.getOutputStream());
        try {
    
             ObjectInputStream ois = new ObjectInputStream (is);
             Person p= (Person) ois.readObject();

            System.out.println(p.toString());
            pw.write("Erfolg \n");
            pw.flush();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        finally{
            is.close();
            pw.close();
        }

        }

Aber damit habe ich jetzt natürlich nicht den eigentlichen Fehler in Deinem Code verbessert sondern nur die Applikation zum Laufen gebracht. Du solltest aber auch ruhig einmal meinen Hinweis probieren. Vom Code her wäre es in etwa folgendes (direkt im Form geschrieben und ungeprüft):

Java:
int pos = 0;
int size = 1024;
byte[] pb=new byte[1024];
int bytesRead = 0;
while((bytesRead=is.read(pb, pos, size-pos))!=-1){
   pos +=bytesRead;
   System.out.println("Read "+bytesRead +" Bytes.");
}
Be aware that this solution will simply be stuck if you receive more data than fit into the buffer. You will fill up the buffer and then loop with reading 0 bytes over and over!

And while thinking about this solution: The loop will run as long as the the stream is open. The Server is not closing the connection so your application simply hangs with reading 0 bytes. So this is not a good solution.

You always need to implement a protocoll that knows when some part is read. So for example in my IRC application I had a thread that was receiving data and stores it. Whenever I received data I checked for a newline (which was a separator in the IRC protocoll) and then evaluated the message. The objectStream is telling on the stream what the size of the object is, so it can request that number of bytes from the stream.

I hope this was helpful.

With kind regards,

Konrad
 

Klösp

Aktives Mitglied
Hallo Konrad,

vielen Dank erstmal.
Ich hätte dazu schreiben sollen, dass es sich hier nur um einen Test handelt. Also ohne großen Sinn dahinter.
Bisher hatte ich immer nur Strings hin und her geschickt und ich wollte einfach mal testen wie das mit anderen Objekten funktioniert.
Die erste Lösung hatte ich davor auch so in etwa stehen und die funktioniert auch.
Nun wollte ich aber eben ausprobieren, wie es funktionieren könnte wenn man das in Form eines Byte[] bekommt.

Da war halt eben mein Ansatz:
1.byte Array empfangen
2. wieder in Object wandeln

Den Code mit der verbesserten Schleife hab ich ausprobiert. Das Ergebnis ist leider das selbe wie voher auch.

Oder gibt es noch einen anderen Ansatz das zu machen (für den Fall das man ein Byte[] bekommt)

Vielen Dank
 
K

kneitzel

Gast
Hallo,

das eigentliche Problem dürfte wirklich sein, dass die Schleife so lange läuft, bis die Verbindung weg ist. Dies kannst Du ja einmal testen, indem Du den Code wie folgt anpasst;
- der Client sendet die Daten und schliesst danach die Verbindung. (ggf. noch ein kurzes Thread.Sleep, aber das sollte eigentlich nicht notwendig sein.)
- der Server sendet nichts zurück.

Dann solltest Du erst einmal sehen, ob meine Vermutung korrekt ist.

Wenn dies so ist, dann erweiterst Du die Lösung wie folgt:
Wenn Du das Bytearray hast, dann ermittelst Du erst die Länge. Und ehe Du das byte-Array sendest, sendest Du die Länge. (Also z.B. als zwei Bytes.)
Auf der anderen Seite liest du dann erst die Länge (also die zwei Bytes) und dann liest Du in der Schleife genau diese Anzahl an Bytes.
Sobald Du die Bytes dann da hast, gibst Du das bytearray mit Deinem Code wieder weiter.

Das sollte dann gehen und würde dem Protokoll entsprechen, das ich schon erwähnt habe. Aber du erkennst, dass Du hier dann mehr Daten überträgst als wirklich notwendig. Das Objekt selbst gibt ja schon eine Länge mit somit hast Du jetzt 2 bytes mehr als vorher. Und dann sind da ja auch noch einige Dinge mehr drin wie Klassenname und so.

Du kannst also Dein Byte-Array anders aufbauen (So du mit Byte-Array arbeiten willst). Du kannst für Dein Protokoll z.B. vorsehen, dass Du Nachrichten durchnummerierst:
00: Verbindung beenden. - Hier kommt nichts nach.
01: Nachricht: Zeichenfolge kommt, Ende mit 00
02: Person: Vorname, 00, Nachname, 00, Alter
Dann kannst Du ein Byte lesen und dann hast Du ein Switch Befehl. Bei 0 beendest Du die Verbindung. Bei 1 liest Du Bytes bis Du ein 00 gelesen hast und wandelst das dann als ASCII um in Text. (Also kein Unicode. Wenn Du Unicode haben willst, könntest Du erst eine Byteanzahl bringen oder so.) ....

Dann hast Du ein Protokoll auf Byte-Ebene, welches nicht in so eine Endlosschleife geht.

Aber jetzt habe ich ganz aus den Augen verloren: Das Problem mit der Endlosschleife hast Du verstanden? Dieses while != -1 endet ja erst, wenn die Verbindung beendet wird....

Mit den besten Grüßen,

Konrad
 

Klösp

Aktives Mitglied
Vielen Dank

Ich nehme an, dass du mit deiner Vermutung recht hast.
Allerdings bekomme ich bei dem Versuche bei deserialsieren mit
Java:
 Person p= (Person) ois.readObject();
noch eine
java.io_OptionalDataException
.

Zu der Endlosschleife:
Ja , ich denk ist jetzt klar. Das war wohl ein Denkfehler von mir. Hab angenommen, wenn -1 zurückgegen wird, wird nichts empfangen.
Aber es wird ist ja wohl so wie z.B bei den BufferdReadern die dann null zurück geben wenn der Output-Steam nicht vorhanden ist und eben nicht dann (wie ich fälschlicherweise dachte)wenn nix gesendet wird.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
8 ByteArray per Netzwerk verschicken Netzwerkprogrammierung 6
K Tabelle im Web über Listener aufrufen Netzwerkprogrammierung 1
F Verbindung zu einem LDAP Server über Java Netzwerkprogrammierung 4
S Socket Bilder über Socket Senden Netzwerkprogrammierung 0
B Zip Dateien über FTP laden Netzwerkprogrammierung 2
x46 byte[] über BufferedReader auslesen Netzwerkprogrammierung 18
E Socket Parameter über Sockets übergeben und auslesen ! Netzwerkprogrammierung 5
L Webbasierte Anwendung - Authentifizierung über LDAP/ActiveDirectory Netzwerkprogrammierung 5
J Probleme mit Multicast über IPv6, DatagramChannel Netzwerkprogrammierung 1
S Daten über TCP/IP senden Netzwerkprogrammierung 3
T Broadcast-message über spez. Netzwerk-Schnittstelle Netzwerkprogrammierung 1
T Mikrofonaudio über Java Server an Webbrowser streamen Netzwerkprogrammierung 13
M Erstelltes Programm über Internet Browser ausführen Netzwerkprogrammierung 26
T VPN-Verbindung über Java Netzwerkprogrammierung 4
V Einfachen Javaserver über das Internet erreichbar machen Netzwerkprogrammierung 2
J FTP Upload über Proxy funktioniert nicht Netzwerkprogrammierung 1
E Kurze Textnachrichten über einen Server von meinem Handy auf den Computer laden. Netzwerkprogrammierung 9
J FTP FTP Zugriff über Proxy Server Netzwerkprogrammierung 1
Thallius Java Application über ZScaler benutzer? Netzwerkprogrammierung 0
J Chat Server starten über GUI problem Netzwerkprogrammierung 4
V einfaches hin und her von Text über Server Netzwerkprogrammierung 2
P RMI Client Server Programm über Internet Netzwerkprogrammierung 2
antonbracke Multiuser Software über XMPP Server Netzwerkprogrammierung 1
Z Verbindung zwischen 2 Rechnern über ServerSockets nicht möglich Netzwerkprogrammierung 3
cezary Socket ServerSocket starten über GUIIm unterstehenden Code versuche Netzwerkprogrammierung 6
I ASCII über serielle Schnittstelle Netzwerkprogrammierung 1
N RMI "RMI über Lan funktioniert nicht" & "RMI-Server im Lan scannen" Netzwerkprogrammierung 13
L Mit Java über PHP in MySQL anmelden (Login script) Netzwerkprogrammierung 3
M Socket String Arrays über Socket an Server schicken Netzwerkprogrammierung 2
T Socket Methoden über Internet aufrufen Netzwerkprogrammierung 1
S Socket Kommunikation über Internet Netzwerkprogrammierung 1
X Problem mit vielen Bytes über Socket Netzwerkprogrammierung 23
M allgemeine Frage über Server-Client-Kommunikation Netzwerkprogrammierung 5
P RMI Threads die über RMI auf Datenbank zugreifen Netzwerkprogrammierung 2
S Datei schreiben über Applet Netzwerkprogrammierung 8
G Klassen über Netzwerk kommunizieren lassen Netzwerkprogrammierung 6
J Erster Server-Client läuft auf lokalem Rechner problemlos. Zwei Rechner über das Internet nicht Netzwerkprogrammierung 8
Kjubert Synchronisieren von Objekten über Client/Server - bester Weg? Netzwerkprogrammierung 7
S ImageIcon über Socket schicken (Serialisierung) Netzwerkprogrammierung 6
H Socket Objekte über Socket? Allgemeine Verständnisprobleme in Sachen Socket Netzwerkprogrammierung 3
S Seltsames Verhalten beim Empfangen von Daten über DataInputStream Netzwerkprogrammierung 12
A TCP über UDP Verbindung? Netzwerkprogrammierung 10
C Datei über Socket schreiben und Ereignis lesen Netzwerkprogrammierung 9
D Socket Class über Netzwerk verschicken Netzwerkprogrammierung 2
D JNLP über Webstart funktioniert nicht... Netzwerkprogrammierung 2
J Socket Dateien über Socket auf Server speichern Netzwerkprogrammierung 3
D Socket Datei nur stückweise über Socket verschicken Netzwerkprogrammierung 6
G Bild über Socket schicken - Client/Server Netzwerkprogrammierung 10
A Computer über Internet verbinden Netzwerkprogrammierung 12
N über Java in eine Text-Datei auf einem Server schreiben Netzwerkprogrammierung 2
c_sidi90 ideale Lösung, Screen Capture über Netzwerk Netzwerkprogrammierung 3
S Socket Verschiedene Exceptions beim Übertragen von Bildern über Socket Netzwerkprogrammierung 20
T ArrayList über Netzwerk senden! Netzwerkprogrammierung 5
N Problem über http eine Datei zu senden Netzwerkprogrammierung 4
T Verbindungsversuche über TCP Sockets von mehreren Threads führt zu Serverabsturz Netzwerkprogrammierung 2
V Authentifikation über mehrere Server? Netzwerkprogrammierung 3
C Verbindung zu einem Hostrechner über das Internet herstellen Netzwerkprogrammierung 15
M Map über Webservice übertragen Netzwerkprogrammierung 3
D Mehrere Clients über Java-Sockets Netzwerkprogrammierung 13
P Socket Verbindung über das Internet Netzwerkprogrammierung 2
Z Socket Connection reset by peer nur per IP nicht über localhost Netzwerkprogrammierung 13
ruffio1978 Telnet über ein socket ansprechen Netzwerkprogrammierung 8
F Socket Verbindungen über mehrere Server Netzwerkprogrammierung 4
U Datei über das Netzwerk einlesen und speichern Netzwerkprogrammierung 8
G Klassen über JMX per URLClassloader laden? Netzwerkprogrammierung 2
E Zwei PCs über das Internet miteinander verbinden? Netzwerkprogrammierung 3
E Socketverbindung über das Internet - Timeout? Netzwerkprogrammierung 28
M Socket Bilder über das Netzwerk übertragen Netzwerkprogrammierung 4
E Java über Socket ins Internet? Netzwerkprogrammierung 4
F Socket Daten über verschiedene IP's schicken Netzwerkprogrammierung 5
M Socket JavaProg über einen Clienten steuern Netzwerkprogrammierung 5
M Mail über Exchange versenden Netzwerkprogrammierung 13
F C/S über HTTPS Netzwerkprogrammierung 2
D ...class.getResourceAsStream("/meine.properties") funktioniert nicht über RMI? Netzwerkprogrammierung 3
M ganymed-ssh2.har: ftp-Verbindung über ftp-Proxy Netzwerkprogrammierung 2
J Probleme bei RSA mit byte[] bei Versand über RMI Netzwerkprogrammierung 2
Z File über Socket lesen Netzwerkprogrammierung 3
A HTTP Binärdaten über PHP-Skript in Datenbank schreiben bzw auslesen Netzwerkprogrammierung 2
M Objekt über Object-Stream, empfange "alte" Daten Netzwerkprogrammierung 2
P FTP isFile() über FTP Netzwerkprogrammierung 3
I Socket HTTP Nachrichten über Sockets verschicken Netzwerkprogrammierung 2
N String als byte Array über Socket versenden Netzwerkprogrammierung 8
M Objekt über socket senden/empfangen Netzwerkprogrammierung 3
N Socket File über Socket vom Server an Client versenden Netzwerkprogrammierung 15
P Socket Problem mit Netzwerkverbindung über TCP Netzwerkprogrammierung 12
A UCP Connection über Proxy möglich? Netzwerkprogrammierung 7
V Verbindung zweier Rechner über das Internet mit Sockets Netzwerkprogrammierung 8
F Char über Netzwerk senden Netzwerkprogrammierung 6
S HTTP Login mit CAS Authentisierung über SSL Netzwerkprogrammierung 2
C Befehle über ein GUI an Server senden Netzwerkprogrammierung 15
M Socket Datei über Socket versenden Netzwerkprogrammierung 5
I Objekte über das Netzwerk Netzwerkprogrammierung 5
M Google Translate über Java ansprechen? Netzwerkprogrammierung 13
F Socket ImageIcon über Socket --> Fehler Netzwerkprogrammierung 14
N Datenaustausch zwischen Java-GUI und PHP-Programm über SOAP Netzwerkprogrammierung 19
L RMI Informationen über die Clients herausfinden Netzwerkprogrammierung 5
R HTTP Problem bei Authentifizierung über (Http)UrlConnection Netzwerkprogrammierung 2
1 Kommunikation mit externem Programm über TCP Netzwerkprogrammierung 2
U Informationen über Netzwerkclients herausfinden Netzwerkprogrammierung 2
J Socket Erreichbarkeit eines Java Servers (Socket-Lösung) über das Internet Netzwerkprogrammierung 3

Ähnliche Java Themen

Neue Themen


Oben