Mehrere Datei per DataInput/OutputStream über Socket

Status
Nicht offen für weitere Antworten.

oulegulas

Mitglied
Hallo alle zusammen,

sitze gerade an einem Projekt für die Uni und komme irgendwie nicht weiter.

Was will ich machen?
Ich habe ein Verzeichniss mit mehreren kleineren Dateien (PDF). Diese soll der Server einzeln an den Client senden.
Soweit so gut. Das Problem daran ist, dass ich keine Ahnung habe, wie der Client erkennen soll, dass gerade eine neue Datei angekommen ist, da er immer Blöcke zu je 1024 Byte bekommt. Daraus resultieren auf der Client- Seite auch ein Haufen Dateien zu je 1024 Byte.

Zur Verdeutlichung ein wenig Code:

Hier der Teil der Serverkomponente:
Java:
public void sendSplitedPDFFiles(String splitedDir) {
                File splitedPDFDir = new File(splitedDir);
                String[] slideFiles = splitedPDFDir.list(new PDFFilenameFilter());
                for (int i = 0; i < slideFiles.length; i++) {
                        try {
                                log.trace(slideFiles[i]);
                                fileIn = new FileInputStream(splitedPDFDir.getAbsolutePath()
                                + System.getProperty("file.separator") + slideFiles[i]);
                                while (fileIn.available() > 0) {
                                        stringBuffer.append(fileIn.read(buffer));
                                        pdfOutStream.write(buffer, 0, fileIn.read(buffer));
                                }
                                fileIn.close();
                        } catch (FileNotFoundException e) {
                                log.error("Could not find the given file. " + e.getMessage());
                        } catch (IOException e) {
                                log.error("Could not send the file: slide_" + (i + 1) + ".pdf "
                                + e.getMessage());
                        }
                }
        }

Dazu noch die Methode zum empfangen:
Java:
public void receivePDFFiles(File dir) {
                log.trace("receive pdf files save it to " + dir.getAbsolutePath());
                System.out.println(dir.list().length);
                try {
                        while (true) {
                                log.trace("try to receive");
                                int bytesRead;
                                bytesRead = pdfInStream.read(buffer);
                                if (bytesRead == -1) {
                                        break;
                                }
                                pdfFileOut.write(buffer, 0, bytesRead);
                                pdfFileOut.close();
                        }

                } catch (IOException e) {
                        log.error("Error while reading from stream. " + e.getMessage());
                }
        }

Ich wäre sehr verbunden um Hinweise, die mir helfen, dieses Problem zu lösen ;)

Beste Grüße und vielen Dank im Vorraus,

Martin
 

sparrow

Top Contributor
Da musst du, wennd du so vorgehen willst, ein eigenes Protokoll entwickeln.

Eine Möglichkeit wäre:

Du möchtest eine Datei Senden die 41982 Bytes hat

1Byte (Länge der Bytes für die Größe der Datei) (in unserem Fall also 5)
5Byte (Gibt die Länge der eigentlichen Datei an, also: 4 1 9 8 2)
41982 Bytes Datei

Der Client kann das entsprechend auswerten und wegspeichern.
Das lässt sich natürlich noch optimieren und verfeinern. Inkl. Dateinamen, etc.
 

Ebenius

Top Contributor
Du möchtest eine Datei Senden die 41982 Bytes hat

1Byte (Länge der Bytes für die Größe der Datei) (in unserem Fall also 5)
5Byte (Gibt die Länge der eigentlichen Datei an, also: 4 1 9 8 2)
Dann schlage ich allerdings vor, die Länge nicht dezimal aufzuschlüsseln, sondern unsigned binär zu übertragen:

1Byte (Länge der Bytes für die Größe der Datei) (in unserem Fall also 2)
2Byte (Gibt die Länge der eigentlichen Datei an, also: A3 FE)
41982 Bytes Daten

Ebenius
 

oulegulas

Mitglied
Ich habe mal versucht die Größe mitzuschicken. Dies geschieht auf folgendem Weg:
Java:
pdfOutStream.writeLong(new File("pfad").length());

Auf der Client- Seite lese ich das ganze dann wieder ein:

Java:
long i = pdfInStream.readLong();
byte[] buff = new byte[Integer.parseInt(Long.toString(i))];
log.trace("Read INT " + i + " " + Long.toString(i) + " "
	+ Integer.parseInt(Long.toString(i)));
log.trace("try to receive");
int bytesRead;
bytesRead = pdfInStream.read(buff);

Auf Client- Seite fliegt mir folgende Exception um die Ohren:
Code:
13:34:13,887 TRACE ClientPDFThread:68 - Read INT 19728 19728 19728
13:34:13,887 TRACE ClientPDFThread:70 - try to receive
Exception in thread "Thread-3" java.lang.NumberFormatException: For input string: "948389091815964349"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
	at java.lang.Integer.parseInt(Integer.java:459)
	at java.lang.Integer.parseInt(Integer.java:497)
	at de.beeld.network.ClientPDFThread.receivePDFFiles(ClientPDFThread.java:67)
	at de.beeld.network.ClientPDFThread.run(ClientPDFThread.java:86)

Der Server weigert sich mit der Meldung:
Code:
Exception in thread "Thread-5" java.lang.ArrayIndexOutOfBoundsException

Irgendwie fühl ich mich überfordert :toll:
 
Zuletzt bearbeitet von einem Moderator:

sparrow

Top Contributor
Ich werde aus deinem Code nich schlau, weil es immer nur Ausschnitte sind.
Der Fehler ist klar: der Client versucht etwas auf INT zu parsen was nicht in den Wertebereich passt.

Schreib doch den Code für die Übertragung in eine extra Klasse oder Methode, dann ist das von dem Rest getrennt und kann hier auch übersichtlich am Stück gezeigt werden.

Du solltest das ganze sequentiell abarbeiten, wie bei Netzwerkprotokollen üblich.
Der Server sendet nacheinander, wie open von Ebenius beschrieben, und der Client wertet das nacheinander aus.
Client prüft das 1. Byte, erkennt wieviele der nächstn Bytes die Gesamtlänge der Datei angeben. Liest die nächsten Bytes um die Größe zu ermitteln. Liest danach die Anzahl von Bytes und schreibt die in eine Datei die er mitgeteilt bekommen hat.
 

oulegulas

Mitglied
Der komplette Code wäre einfach zu viel für diesen Thread, deswegen habe ich ihn nicht gepostet. Prinzipiell ist der Code über Sourceforge erreichbar, bei Interesse einfach PM.

Ich habe es jetzt soweit hinbekommen, das Senden und Empfangen über mein vorhandenes Protokoll zu steuern.

Allerdings kann ich nicht immernoch nicht herausfinden wann eine Datei zu Ende ist.

Daher nochmals ein paar Schnipsel, in der Hoffnung, dass sie doch etwas Aussagekraft haben.

Der Teil zum senden; Eine Datei öffnen und so lange einlesen, bis es nichts mehr gibt und in den OutStream schreiben.
Java:
log.trace("Current file I try to send: "
	+ currentFile.getAbsolutePath());
fileIn = new FileInputStream(currentFile);
while (fileIn.available() > 0) {
	pdfOutStream.write(buffer, 0, fileIn.read(buffer));
}
fileIn.close();


Der Teil zum empfangen; solange 1024 Byte einlesen, bis -1 kommt. Nur leider kommt kein -1. Irgendwie; Und ich weiß nicht wie ich sonst überprüfen soll, dass das lesen aus dem InStream vorbei ist...
Java:
while (loop) {
	int bytesRead;
	bytesRead = pdfInStream.read(buffer);
	totallyBytesRead = totallyBytesRead + bytesRead;
	log.trace("Currently read: " + bytesRead);
	if (bytesRead == -1) {
		log.info("Finished transfer of " + slideName + " and read "
			+ totallyBytesRead + " bytes for this file.");
		pdfFileOut.close();
		Client.getInstance().sendMessage(NetworkMessages.PROCEED,
							slideName);
		loop = false;
	}
	pdfFileOut.write(buffer, 0, bytesRead);
	log.trace("Read " + totallyBytesRead + " of current slide "
		+ slideName);
}
 

sparrow

Top Contributor
Moment, ein -1 kommt erst wenn du von Serverseite die Verbindung schließt. Das willst du ja nicht, du willst ja nacheinander die Dateien senden.
Woran scheitert es denn genau, bzw. was hast du von den Vorschlägen hier im Thread schon umgesetzt? Überträgst du die Größe der Datei vor der eigentlichen Datei? Weiß der Client wieviele Bytes er zu erwarten hat?
 

oulegulas

Mitglied
Ich habe versucht, den Buffer so groß wie die Größe zu machen, aber da kam eine NumberFormatException.

Ich denke, da war irgendwie der Cast von Long (welches du bekommst, wenn du File.length() benutzt) nach int (was du brauchst, wenn du den Buffer anlegst buffer = new byte[filesize];).

Das Problem ist eben momentan, wie ich herausfinde, dass die Datei fertig übertragen ist.
Gelöst habe ich es (recht unschön ehrlich gesagt), dass ich schaue, ob der gelesene Buffer kleiner als 1024 ist.
Java:
while (loop) {
	int bytesRead;
	bytesRead = pdfInStream.read(buffer);
	totallyBytesRead = totallyBytesRead + bytesRead;
	log.trace("Currently read: " + bytesRead);
	if (bytesRead != 1024) {
		pdfFileOut.write(buffer, 0, bytesRead);
		log.info("Finished transfer of " + slideName + " and read "
			+ totallyBytesRead + " bytes for this file.");
		pdfFileOut.close();
		Client.getInstance().sendMessage(NetworkMessages.PROCEED,
			slideName);
		loop = false;
	}
	pdfFileOut.write(buffer, 0, bytesRead);
	log.trace("Read " + totallyBytesRead + " of current slide "
		+ slideName);
}
 

sparrow

Top Contributor
Das funktioniert so nicht.

Fühl dich jetzt bitte nicht verscheißert, aber mir fällt es immer einfacher so etwas zu verstehen wenn ich das bildlich erklärt kriege.

Ich versuch dir das mal auf eine einfache Weise zu erklären. Wenn du zwischen 2 PCs eine TCP/IP-Verbindung aufbaust, dann ist das für dich schonmal ein ziemlich simples Protokoll. Im Prinzip eine Straße mit einer Fahrbahn von A nach B und eine Fahrbahn von B nach A. Warum ist das für dich simpel? Weil du dich um die Übertragung an sich nicht kümmern musst. Du setzt ein Auto nach dem anderen auf eine von den beiden Spuren und schon fährt das zu dem anderen PC. Das die sich nicht gegenseitig überholen bzw. der ADAC ein Auto wieder flott macht wenn es liegen geblieben ist, darum kümmert sich bereits das Protokoll für dich.
Sobald die Straße erst mal da ist funktioniert das alles sehr gut. Beide Seiten können sogar reagieren wenn die andere Seite beschließt die Verbindung abzubauen und die Straße quasi abzureißen (eine Ausnahme ist hier das unerwartete Ende durch so etwas wie Stecker ziehen, aber das lassen wir hier mal außen vor).

So, du hast dir nun eine Puffer geschrieben, so eine Art Fähre. 1024 Autos gehen in die Fähre rein. Es kommen 960. Fehlen noch 64. Was passiert? Die Fähre fährt gar nicht los weil sie nicht voll ist. Das ist auch gut so. Es kann nämlich auch sein, dass son Opa mit Wackeldackel den ganzen Verkehr aufhällt und in Wirklichkeit noch viele, viele Autos fehlen.
Der Server könnte die Verbindung schließen, das würde der Client merken, allerdings ist das ja nicht das was du erreichen wolltest.

Den Lösungsweg habe ich oben schon beschrieben.
Du lässt 1 Auto bei A losfahren das anzeigt wieviele der nächsten Autos (in diesem Beispiel 3) die Gesamtgröße der Daten angeben.
B empfängt das Auto und sieht, aha die nächsten 3 Autos enthalten die Gesamtzahl der zu erwartendenden Dateidatenautos. (Hier könnte B ein 'OK schick los' antworten)
A lässt 3 Autos losfahren die die Information tragen wieviele Autos für die Datendatei zu erwarten sind (sagen wir 12859).
B empfängt diese 3 Autos (hier muss natürlich migezählt werden), wertet den Wert aus und weiß nun, dass die nächsten 12859 Autos Dateidatenautos sind. (Hier könnte B ein 'OK schick los' antworten)
A schickt nun 12859 Autos auf den Weg.
B zählt die Autos mit und weiß nach 12859 Autos, dass die Dateiübertragung nun beendet ist. Wenn der Server anschließend die Verbindung schließt kommt definitiv nichts mehr, ansonsten könnte B auf das nächste Auto warten das ihm sagt wieviele der nächsten Autos die Menge der Dateidatenautos enthalten und es geht von vorne los...
 
Zuletzt bearbeitet:

oulegulas

Mitglied
Ich fühle mich nicht verscheißert, im Gegenteil danke ich dir, dass du versuchst, es mir so einfach zu erklären.

Das es nicht funktioniert, is nicht richtig, es funktioniert schon. Die Dateien werden ohne jegliche Probleme übertragen, es fliegt lediglich am Ende eine IOException. Dh, er überträgt auch einen Buffer, der kleiner ist als 1024 (zB 96 oder 243 Byte).

Aber ich habe durch deine nette Erklärung noch eine Idee bekommen, wie ich das umgehen könnte. Mal probieren :)
 

oulegulas

Mitglied
Ich fühle mich nicht verscheißert, im Gegenteil danke ich dir, dass du versuchst, es mir so einfach zu erklären.

Das es nicht funktioniert, is nicht richtig, es funktioniert schon. Die Dateien werden ohne jegliche Probleme übertragen, es fliegt lediglich am Ende eine IOException. Dh, er überträgt auch einen Buffer, der kleiner ist als 1024 (zB 96 oder 243 Byte).

Aber ich habe durch deine nette Erklärung noch eine Idee bekommen, wie ich das umgehen könnte. Mal probieren :)
 

sparrow

Top Contributor
Das freut mich.

Und wenns nicht geht nehmen wir hier mal deinen Code Zeile für Zeile auseinander ;)
Aber bitte mit der Übertragung der Größe vorweg, mir fällt nämlich keine andere Möglichkeit ein.
 

oulegulas

Mitglied
Also gelöst...

Ich hab die Dateigröße in meinen Paketen mitgeschickt, und schaue nun einfach, ob ich schon so viele Bytes gelesen habe, wie die Datei groß sein sollte :)

Java:
try {
	while (loop) {
		int bytesRead;
		bytesRead = pdfInStream.read(buffer);
		totallyBytesRead = totallyBytesRead + bytesRead;
		pdfFileOut.write(buffer, 0, bytesRead);
		if (totallyBytesRead == Integer.parseInt(Long.toString(fileSize))) {
			loop = false;
		}
	}
}

Großen Dank für die nette Hilfe :)
 
Zuletzt bearbeitet:
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
izoards Mehrere TCP Verbindungen auf einen Server [alles Local] Netzwerkprogrammierung 2
Aruetiise Socket Mehrere Clients Netzwerkprogrammierung 4
E Mehrere Sockets Netzwerkprogrammierung 2
C Mehrere Spielewelten im Multiplayer Netzwerkprogrammierung 2
J Framework mehrere Clients/ Server-Broadcast/oracle XE/ XML Netzwerkprogrammierung 1
V Server / mehrere Clients / MySQL / Konzept Netzwerkprogrammierung 2
S Server - Mehrere Klassen sollen Daten senden und empfangen Netzwerkprogrammierung 25
Creylon Socket Mehrere gleichzeitig eingehende Nachrichten Netzwerkprogrammierung 8
N SOCKET mehrere Requests, keep Alive serverspezifisch? Netzwerkprogrammierung 3
7 Mehrere Verbindungen gleichzeitig in einem Thread mit ApacheHTTP Netzwerkprogrammierung 7
Z Socket [Chatprogramm] Mehrere Clients an einen Server Netzwerkprogrammierung 10
V Authentifikation über mehrere Server? Netzwerkprogrammierung 3
G Socket Mehrere Clientanmeldungen am Server Netzwerkprogrammierung 13
D Mehrere Clients über Java-Sockets Netzwerkprogrammierung 13
cedi Socket Mehrere Clients an einem Server Netzwerkprogrammierung 4
B SSH mit Jsch, mehrere Befehle senden Netzwerkprogrammierung 4
F Socket Verbindungen über mehrere Server Netzwerkprogrammierung 4
M Jetty Konfiguration mehrere Handler? Netzwerkprogrammierung 2
F UDP Server - mehrere Pakete auf einmal Netzwerkprogrammierung 12
A Mehrere gleich Packete behandeln Netzwerkprogrammierung 4
L Socket Chat Server für mehrere Clients Netzwerkprogrammierung 7
R mehrere MySQL-Zugriffe Netzwerkprogrammierung 3
B Paralleler Dateitransfer: Ein Client - Mehrere Sockets? Wie connecten? Netzwerkprogrammierung 16
S Mehrere Attachments mit JavaMail API auslesen Netzwerkprogrammierung 3
A Datenverteilung: Mehrere Threads verwenden? Netzwerkprogrammierung 4
T Netzwerkchat Problem: Mehrere Nachrichten ~ Anfängerproblem Netzwerkprogrammierung 3
W Bestimmt IP Adresse verwenden wenn man mehrere hat Netzwerkprogrammierung 5
D Clients sollen mehrere Sessions starten Netzwerkprogrammierung 11
A Jakarta Commons HTTPClient: Mehrere Requests gleichzeitig Netzwerkprogrammierung 2
R Mehrere Dateien über einen Socket senden Netzwerkprogrammierung 2
G Nachricht an mehrere Clients schicken Netzwerkprogrammierung 10
L mehrere Streams über einen Socket? Netzwerkprogrammierung 8
V Mehrere Streams durch einen Stream senden Netzwerkprogrammierung 14
E Mehrere / bestimmte Netzwerkkarten ansteuern Netzwerkprogrammierung 10
F Mehrere Attachments mit JavaMail API Netzwerkprogrammierung 2
G Proxy und mehrere Verbindungen Netzwerkprogrammierung 4
G Mehrere SSL Verbindungen Netzwerkprogrammierung 2
A Mit Client auf mehrere Server zugreifen Netzwerkprogrammierung 5
M Mehrere Ports gleichzeitig abhören Netzwerkprogrammierung 5
TRunKX Ein Port mehrere Verbindungen? Netzwerkprogrammierung 7
G Server an mehrere Clients Netzwerkprogrammierung 15
L JavaMail: Automatisches Email Versand (mehrere Empfänger) Netzwerkprogrammierung 4
U Einen HandlerThread, der mehrere Verbindungen verwaltet? Netzwerkprogrammierung 2
X mehrere Request über eine HttpURLConnection Netzwerkprogrammierung 2
A Bei FTP Übertragung wird Datei nicht komplett übertragen Netzwerkprogrammierung 2
J Datei Download vom Server Netzwerkprogrammierung 8
H Datei mit Anhang via http "hochladen" Netzwerkprogrammierung 16
E JCIFS - Smb - Datei kann nur von einem Benutzer bearbeitet werden Netzwerkprogrammierung 1
Aruetiise Socket Datei Endung Netzwerkprogrammierung 6
A FTP wie kann ich von java auf datei in fpt://192.168.178.1 lesen/schreiben? Netzwerkprogrammierung 3
K HTTP Formulare füllen und Datei downloaden Netzwerkprogrammierung 23
B JSch Filetransfer ohne KnownHosts Datei? Netzwerkprogrammierung 0
A Datei erzeugen und auf der Weboberfläche downloaden (Tomcat) Netzwerkprogrammierung 4
Sogomn HTTP Datei herunterladen Netzwerkprogrammierung 13
C Inhalt einer .JPG Datei in einen OutputStream schreiben? Netzwerkprogrammierung 10
F FTP FTPClient Datei lässt sich nicht öffnen Netzwerkprogrammierung 4
F HTTP Serialisierte Objekte aus Datei von Server Netzwerkprogrammierung 1
T Anwendungseinstellungen ohne Datei übertragen? Netzwerkprogrammierung 8
F FTP Einzelne Datei von FTP-Server überprüfen Netzwerkprogrammierung 0
L FTP Lesen einer Datei vom Server - Aufgehangen Netzwerkprogrammierung 0
M jsf-seite beim hinzufügen einer csv-datei in einen ordner aktualiseren Netzwerkprogrammierung 0
D Einfache Verbindung zu Linux Server und Datei auslesen Netzwerkprogrammierung 13
S Datei(XML) per RMI an Server schicken Netzwerkprogrammierung 0
V Datei Download Fenster Netzwerkprogrammierung 9
S Datei schreiben über Applet Netzwerkprogrammierung 8
C Socket Datei Übertragung Netzwerkprogrammierung 5
D Datei hochladen zu PHP Server Netzwerkprogrammierung 8
C Datei über Socket schreiben und Ereignis lesen Netzwerkprogrammierung 9
K HTTP Eigener Http Response für Datei-Download Netzwerkprogrammierung 4
D Socket Datei nur stückweise über Socket verschicken Netzwerkprogrammierung 6
T Datei downloaden ohne den Dateinamen zu kennen Netzwerkprogrammierung 2
H Datei in DropBox schreiben Netzwerkprogrammierung 23
N über Java in eine Text-Datei auf einem Server schreiben Netzwerkprogrammierung 2
V Datei auf Server Schreiben Netzwerkprogrammierung 18
N Einen Server als ausführbare Datei exportieren Netzwerkprogrammierung 15
N Problem über http eine Datei zu senden Netzwerkprogrammierung 4
B FTP Datei auslesen ohne einloggen möglich? Netzwerkprogrammierung 19
C Datei auf server speichern Netzwerkprogrammierung 16
P FTP Nochmal wachsende Datei per FTP lesen Netzwerkprogrammierung 9
W Datei automatisiert kopieren! Netzwerkprogrammierung 5
P Wachsende Datei per FTP lesen Netzwerkprogrammierung 2
U Datei über das Netzwerk einlesen und speichern Netzwerkprogrammierung 8
S Servlet - Datei kann nicht gelöscht werden Netzwerkprogrammierung 12
G Txt datei von Website downloaden Netzwerkprogrammierung 8
R HTTP Apache HTTP Client: Request mit angehängter Datei Netzwerkprogrammierung 2
I HTTP Datei Uploaden mit http und Sprache anpassen Netzwerkprogrammierung 7
1 Datei senden/empfangen funzt nicht... Netzwerkprogrammierung 5
S ActiveMQ, JMS und Datei übertragen Netzwerkprogrammierung 25
M Socket Datei über Socket versenden Netzwerkprogrammierung 5
U Web Datei downloaden und bei Änderungen wieder zurückspielen Netzwerkprogrammierung 5
M Class-Datei aus Eclipse mit Xampp Netzwerkprogrammierung 4
A HTTP Download einer Datei mit "Statistiken" Netzwerkprogrammierung 2
B Zugriff auf eine Text- und XML-Datei Netzwerkprogrammierung 4
Dit_ FTP, Datei Hochladen Netzwerkprogrammierung 4
Ollek Download einer Datei durch SFTP mit Java Netzwerkprogrammierung 12
J Datei übertragen ja String + datei übertragen nein Netzwerkprogrammierung 5
P Name der Download-Datei ermitteln Netzwerkprogrammierung 8
N Socket TCP Datei Transfer Netzwerkprogrammierung 2
L Java über php datei lesen? Netzwerkprogrammierung 18
P Socket Datei von Client zum Server übertragen --> Weiterleitung an Clients Netzwerkprogrammierung 16

Ähnliche Java Themen

Neue Themen


Oben