Java-Programm zum Datenaustauschen

Hallo alle zusammen,
ich hab ein Programm geschrieben, mit dem man beliebige Daten vom Client auf den Server senden kann. Für das senden verwende ich den GZIPOutputStream, das funktioniert auch, zum Empfangen den GZIPInputStream. Das Programm ist im Hemnetz getestet und funktioniert. Leider lässt die Geschwindigkeit zu wünschen übrig. Hat wer eine Idee, wie man die KB/s steigern kann? Quellcode folgt.
Danke schon mal an alle, die sich mit dem Problem beschäftigen.
Gruß Yannick

Edit:


import graphisches.DateiAuswahl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class FileClient {

	private static Socket server;
	private static PrintWriter out;
	private static Scanner in;
	private static InputStream datin;
	private static OutputStream zip;
//	private static FileOutputStream datout;

	public static void dateiSenden() {

		datin = null;
		out = null;
		zip = null;
		File f = null;

		String s = javax.swing.JOptionPane
				.showInputDialog("Bitte Server-IP eingeben:");

		try {
			server = new Socket(s, 1234);

//			out = new PrintWriter(server.getOutputStream(), true);
			
			zip = new GZIPOutputStream(server.getOutputStream(), 65536, true);

			f = DateiAuswahl.getSelFile();
//			out.println(f.getName());

			datin = new FileInputStream(f);
			
			byte[] buffer = new byte[0xFFFF];
			
			for (int n; (n = datin.read(buffer)) != -1;) {
				zip.write(buffer, 0, n);
			}

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (datin != null)
				try {
					datin.close();
				} catch (IOException e) {
				}

			if (out != null)
				out.close();
		}

	}

	public static void main(String[] args) {
		FileClient.dateiSenden();
	}

}

Edit:


import java.io.*;
import java.net.*;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class FileServer {

	private static Scanner in;
	private static PrintWriter out;
//	private static FileInputStream datin;
	private static OutputStream datout;
	private static InputStream enzip;

	

	public static void verbinden() throws IOException {

		ServerSocket server = new ServerSocket(1234);
		Socket client = null;

		while (true) {
			try {

				client = server.accept();

//				in = new Scanner(client.getInputStream());
				out = new PrintWriter(client.getOutputStream(), true);

				ArrayList<Socket> clients = new ArrayList<Socket>();
				clients.add(client);

				erstelleDatei(in, client.getInputStream());

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				if (client != null)
					try {
						client.close();
					} catch (IOException e) {
					}
			}
		}
	}

	public static void erstelleDatei(Scanner s, InputStream is) {

		datout = null;
		try {
			datout = new FileOutputStream(System.getProperty("user.home") + "/"
					+ "try.iso");
			
			enzip = new GZIPInputStream(is, 65536);

			for(int i; (i= enzip.read()) != -1;  ) {
				datout.write(i);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (datout != null) {
				try {
					datout.close();
				} catch (IOException e) {
				}
			}
		}

	}
	
	private static void dateiSenden(){
		
//		datin = null;
		
		
	}

	public static void main(String[] args) {
		try {
			FileServer.verbinden();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

Edit:

P.S. Wie kann man Code „ordentlich“ einfügen ? Sorry, bin neu :wink:

schade, aber auf den text aus dem anderen forum kann nich nicht mehr zugreifen

aber : für code gilt generell mindestens

-Tag, ansonsten für spezielle sprache z.b. ```-Tag oder ``` 
```php
 und andere (google mal nach "vb code tags")

grob überflogen kann ich jetzt keine große bremse erkennen, auch wenn mir rätzelhaft ist warum du versuchst die daten mit nem GZIP-stream noch mal etwas zu verkleinern vor der übertragung
im LAN sollte das grundsätzlich mit höchst-geschwindigkeit ablaufen, ansonsten könnten es eventuell die beteiligten rechner sein deren leistung nicht reicht
und ins netz zu nem server begrenz natürlich dein net-upload

Seit heute Morgen haben wir eine neue Forensoftware. Die Funktionen zum komfortablen Einfügen von Code (über Buttons) werden in den nächsten Tagen eingepflegt.
So lange musst du die Tags von Hand schreiben.

Für Java, wie in deinem Fall:
[noparse]//Dein Code[/noparse]

Ich werde das mal für dich erledigen.

Hmm, doppelt hält besser :-/. Sorry LeX, da habe ich wohl die gleichen Änderungen ebenfalls gemacht ^^

Okay, danke. In Zukunft wird sowas nicht mehr vorkommen.

Hmm, dann muss ich mich mit der Geschwindigkeit wohl abfinden… Trotzdem danke für die Antworten :slight_smile:

Hast du es schon ohne GZipOutputStream versucht?
Grüße,
Freak

PS: Es fehlt ein NOPARSE man findet im Code diesen Mist : ‘
Der Thread Ersteller hatte sicher nicht die Absicht sowas hinzuschreiben.

Blödsinn. Hab nur kurz drüber geschaut: Du hast im Code gleich zwei Fehler gemacht:

  1. Dein Server liest byte-weise, und nicht Blockweise. Schau dir mal die anderen read() Methoden an. Tipp: Lies Daten mal in 8kbyte Blöcken ein. Und dann kannst du noch mit 64k und 1024k experimentieren. Im Client machst du das ja schon… Wieso nicht auch im Server?
  2. Wenn du viel Daten über eine TCP Verbindung schaufelst, dann kannst du den Nagle-Algorithmus abschalten. Das bringt auch nochmal einiges. Google mal nach „setTcpNoDelay“ …

Gruß
Alex

Ich hab versucht die Fehler zu beheben. Jetzt hab ich eine gute Geschwindigkeit, aber die Dateien sind auf einem nach dem Senden größer, wie zuvor und lassen sich nicht mehr öffnen.

Client:


import graphisches.DateiAuswahl;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class FileClient_1 {

	private static Socket server;
	private static PrintWriter out;
	private static Scanner in;
	private static InputStream datin;
	private static OutputStream zip;
//	private static FileOutputStream datout;

	public static void dateiSenden() {

		long start = System.currentTimeMillis();
		datin = null;
		out = null;
		zip = null;
		File f = null;

		String s = javax.swing.JOptionPane
				.showInputDialog("Bitte Server-IP eingeben:");

		try {
			server = new Socket(s, 1234);
			server.setTcpNoDelay(true);

//			out = new PrintWriter(server.getOutputStream(), true);
			
			zip = new GZIPOutputStream(server.getOutputStream(), 65536, true);
			
			out = new PrintWriter(zip, true);

			f = DateiAuswahl.getSelFile();
//			out.println(f.getName());

			datin = new FileInputStream(f);
			
			out.println(f.getName());
									
			byte[] buffer = new byte[0xFFFF];
			
			for(int n ; (n = datin.read(buffer)) != -1; ){
				zip.write(buffer);
			}

		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (datin != null)
				try {
					datin.close();
				} catch (IOException e) {
				}

			if (out != null)
				out.close();
		}
		
		long end = System.currentTimeMillis();
		
		long time = end - start;
		
		int zeit = (int) time;
		
		System.out.println(zeit);

	}

	public static void main(String[] args) {
		FileClient_1.dateiSenden();
	}

}

Server:


import java.io.*;
import java.net.*;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.*;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

public class FileServer_1 {

	private static Scanner in;
	private static PrintWriter out;
//	private static FileInputStream datin;
	private static OutputStream datout;
	private static InputStream enzip;

	

	public static void verbinden() throws IOException {

		ServerSocket server = new ServerSocket(1234);
		Socket client = null;

		while (true) {
			try {

				client = server.accept();
				client.setTcpNoDelay(true);

//				in = new Scanner(client.getInputStream());
				erstelleDatei(in, client.getInputStream());

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} finally {
				if (client != null)
					try {
						client.close();
					} catch (IOException e) {
					}
			}
		}
	}

	public static void erstelleDatei(Scanner s, InputStream is) {

		datout = null;
		try {
			
			enzip = new GZIPInputStream(is, 65536);
			
			in = new Scanner(enzip);
			
			String tri = in.nextLine();
			
			System.out.println(tri);
			
			datout = Files.newOutputStream(Paths.get(System.getProperty("user.home") + 
					"/" + tri), StandardOpenOption.CREATE);
			
			byte[] buffer = new byte[0xFFFF];
			
			for(int n; (n = enzip.read(buffer, 0, 64000)) != -1; ){
				datout.write(buffer);
			}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			if (datout != null) {
				try {
					datout.close();
				} catch (IOException e) {
				}
			}
		}

	}
	
	private static void dateiSenden(){
		
//		datin = null;
		
		
	}

	public static void main(String[] args) {
		try {
			FileServer_1.verbinden();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

und ohne GZIPInputStream hab ich noch nicht versucht, weil wenn ich die Datei doch komprimiere, müssen doch weniger Byte geschickt werden. Oder kann es sein, dass das Komprimieren länger dauert, wie die paar Byte mehr zu schicken ?

Schau dir mal an wofür PrintWriter zu benutzen ist: PrintWriter (Java Platform SE 6)

Zitat:

Prints formatted representations of objects to a text-output stream. This class implements all of the print methods found in PrintStream. It does not contain methods for writing raw bytes, for which a program should use unencoded byte streams.

Wenn das Wort „Writer“ in einer Stream-Klasse vor kommt, dann kannst du davon ausgehen, dass diese Klasse normalerweise nicht dafür gedacht ist Binärdaten zu Schreiben/Lesen …

Deshalb sind deine Daten nach dem Schreiben auch größer als vorher …

Wenn du Strings und Binärdaten gleichermaßen in einem Stream verwenden willst, benutze DataInputStream bzw. DataOutputStream und keine Writer-Streams.

Moment, ich benutze den PrintWriter nur zum Senden des Dateinamens, nicht zum Senden der eigentlichen Datei. Dafür nehme ich den GZIPOutputStream.

Es ist keine gute Idee auf einem Stream unterschiedliche Substreams zu verwenden um mit dem einen Strings und mit dem anderen Bytes zu schreiben…

Dafür gibt’s den http://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html. Damit kannst du beides auf einmal.
Mit writeUTF() schreibst du den Dateinamen in den Stream und mit write() kannst du blockweise die Datei als byte[] rein schreiben.

Würde das dann so verketten:

OutputStream <- GZIPOutputStream <- DataOutputStream

Und auf der anderen Seite wieder zurück

InputStream -> GZIPInputStream -> DataInputStream

Dann mit readUTF() den Filenamen lesen und mit read() die File lesen.

Das Mischen Mischen von Streams sollte man nach Möglichkeit unterlassen. Auch sollte man nur am Ende einer Streamkette lesen oder schreiben und nicht mal in der Mitte und mal am Ende. Unter Umständen wird nämlich von der einen oder anderen Streamklasse gepuffert und Daten “auf vorrat” gelesen… Deshalb fährt man am besten wenn der Stream einen sauberen Anfang und ein sauberes Ende hat und nur am Ende gelesen und geschrieben wird.

Ach ja, noch was:

Ein oft gemachter Fehler ist auch folgender:

Man liest vom einen Stream (z.B. File) und schreibt in den nächsten (z.B. Netzwerk). Dabei sollte man nur soviel schreiben wie man gelesen hat.

In deinem Beispiel hat du ein byte[] mit der Größe 0xffff und liest von der File. Du achtest beim schreiben des byte[] in den nächsten Stream aber nicht darauf wieviel du von der File gelesen hast, sondern schreibst das ganze byte[]… Das ist fatal. Ein read(myByteArray) füllt nicht zwingend das gane byte[] mit Daten. Unter Umständen wird nur ein Bruchteil des möglichen gelesen. Schreiben tust du aber immer das ganze byte[], welches dann noch leere bytes, oder alte bytes am Ende enthält.

Also:

out.write(myByteArray, 0, dataRead);```

Dieses Konstrukt sieht problematisch aus:

[...]
String tri = in.nextLine();
System.out.println(tri);
datout = Files.newOutputStream(Paths.get(System.getProperty("user.home") + 
  "/" + tri), StandardOpenOption.CREATE);
[...]

Offensichtlich soll hier die erste “Zeile” ges gzip-InputStreams gelesen werden, weil dort wohl ein Dateiname steht. Das mag sogar gehen (kenne mich mit dem GZip-Format nicht aus). Problem ist nur, dass Du damit die ersten Bytes “weggelesen” hast und wenn Du den Rest dann liest und in eine Datei schreibst, diese sicher korrupt werden wird. Du musst also entweder die bereits weggelesenen Bytes auch in den Output schieben, oder für den Kopiervorgang einen neuen GZipInputstream erzeugen, damit Du für den Kopiervorgang wieder von Anfang an liest. (Ist im Moment bei Deiner Methode aber nicht möglich, weil Du den InputStream als Parameter nur einmal hast.)

Oder aber gleich den DataOutputStream/DataInputStream in oben genannter Konstellation verwenden…

Also Scanner und Co. sind raus, dafür DataIn- und OutputStreams. Der Puffer wird jetzt auch immer nur soweit ausgelesen, wie weit er auch gefüllt worden ist.

Ich danke Euch für eure super Hilfe !!