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();
}
}
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]
Blödsinn. Hab nur kurz drüber geschaut: Du hast im Code gleich zwei Fehler gemacht:
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?
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“ …
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();
}
}
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 ?
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.
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.
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.)
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.