# Netzwerk-Dateiübertragung optimieren



## tulius (11. Sep 2010)

Tag zusammen.
Ich übertrage mit einem Programm Dateien übers lokale Netzwerk (LAN/WLAN)

Das mache ich derzeit mit dem "Standard-Verfahren":
Server: (verkürzt)


```
byte[] buffer = new byte[32*1024];
    int bytesRead;
    while ((bytesRead = input.read(buffer, 0, buffer.length)) > 0)
    {
        output.write(buffer, 0, bytesRead);
    }
```

Client genauso, liest in den Puffer und schreibt den in die Datei.
Natürlich sind alle Ströme BufferedStreams

Über LAN funktioniert das meistens gut, aber besonders über WLAN ist das furchtbar langsam.
Also:

- Wie kann ich das optimieren und beschleunigen? (besonders für WLAN)
- Spielt die Puffergröße eine entscheidende Rolle für die Übertragungsgeschwindigkeit? (dass bei einem kleinen Puffer zu oft von der Platte gelesen werden müsste ist mir klar, es geht mir um den Einfluss auf die tatsächliche Übertragung
- Würde die Verwendung von java.nio eine in der Praxis tatsächlich relevante Verbesserung der Geschwindigkeit bringen?
- Oder gibt es ein ganz anderes Verfahren, das viel besser geeignet wäre?


----------



## maki (11. Sep 2010)

> Über LAN funktioniert das meistens gut, aber besonders über WLAN ist das furchtbar langsam.


Was heisst denn "gut" und "furchtbar langsam" in MB/Sek?


----------



## tulius (11. Sep 2010)

"Gut" ist ziemlich am Maximum, was so ein 100Mbit-Netzwerk hergibt, durchaus mal 12MB/s
"furchbar langsam" ist schwer zu beziffern, aber ziemlich sicher weniger als 1/20 des Kabelnetzes. Da das Funknetz nur 54MBit hat, wird also höchstens 1/10 der Kapazität genutzt


----------



## maki (11. Sep 2010)

Liegt imho nicht an deinem programm, sondern am WLAN.
Bei WLAN gilt: 54 Mbit ist der Bruttowert, unter idealen Bedingungen sind das meist nicht mehr als 5-10 MBit netto.
300 MBit WLAN sind übrigens unter idealen Bedingungen nur 100MBit netto.

Kannst dir auch mal den Wikipedia Artikel dazu durchlesen: Wireless Local Area Network ? Wikipedia


----------



## Kr0e (11. Sep 2010)

Übertrag doch mal ne Datei mit Windows... WEnns nicht schneller geht, kannst du mit java uach nciht mehr rausholen...


----------



## maki (11. Sep 2010)

Kr0e hat gesagt.:


> Übertrag doch mal ne Datei mit Windows... WEnns nicht schneller geht, kannst du mit java uach nciht mehr rausholen...








*g*


----------



## Empire Phoenix (12. Sep 2010)

uii der gute xkcd ^^

Was helfen könnte wäre bei den einen algorithmus wie auch immer der hias auschalten der bei fehlern kurz pauseiert (nagels? nables?) weiß das es geht aber nicht mehr wie. 

Am rande windows ist ziemlich inneffizient was das protokoll angeht, bei datenfehlern


----------



## Kr0e (13. Sep 2010)

Hallo Empire Phoenix,

ich höre in deiner Aussage eine Abneigung gegen Microsoft  Geht mir ähnlich. Dennoch ist dein Vorwurf Unsinn. Windows ist nicht ineffizient im Allgemeinen. Ich würde es dann deiner Stelle differenzieren. Win 2000 / XP mag durchaus ein schlechtes Protokoll noch besitzen, aber die sind ja auch schon Jahre alt (Win7 z.B. ist sehr effizient aus meiner Sicht als User). Außerdem wüsste ich gern, wie du auf sowas generell kommst :

"Am rande windows ist ziemlich inneffizient was das protokoll angeht, bei datenfehlern "

Reines Bauchgefühl ?! Du hast ja wohl kaum den Source dazu gesehen, wenn doch.. Schick ihn bitte!
So eine Aussage bringt den TO wirklich kein Stück weiter. 

Dein anderer Vorschlag (Nagle) dürfte IMHO keinen Vorteil bringen, ganz im Gegenteil! Eher Nachteile... Der Alg. macht folgendes:
Er wartet bis genug Daten zum Senden anliegen, damit ein TCP Paket mit einer Mindestgröße der MTU (Maximum Transfer Unit)
verschickt werden kann und somit der FlowControl hilft. (Weniger Ack-Befehle, die hin und her gesendet werden müssen)
Von daher solltest du mal lieber schauen, ob der Nagel-Alg. bei dir vlt. aus ist...

Ansonsten meinte ich mit "Schau mal wie schnell es bei Windows ist" nicht die Zeit die beim Kopiertvorgang steht, es gibt ja auch die Uhr rechts unten 

Aber lange Rede kurzer Sinn. WLAN ist und bleibt eben einfach lahm und ineffizient. Da kann dann Windows auch nichts für 

Gruß,

Christopher

PS: Aber jetzt mal abgesehen vom Netzwerk. Dein Code ist sowieso nicht der effizienteste, sonder neine Standardlösung aus dem Lehrbuch =P. Wenn du effizient empfangen und senden willst, solltest du den Zugriff auf deine Festplatte nicht im selben Thread durchführen, wie den Zugriff aufs Netzwerk (Socket). Beides sind synch. IO-Operationen die jeweils relativ lange brauchen.

Am besten wäre ein "HardDiskThread" oder so, der aus einer Liste Buffers liest, die mit einer ID versehen sind und die dann in seinem Thread der Reihe nach auf die HD schreibt. Bei Festplatten solltest du außerdem einen größeren Puffer beim BufferedStream verwenden als 8192 kb (Standard beim BufferedStream) . 128k wären bei heutigen Festplatten schon eher vernüftig. Der Lesekopf muss sonst ständig hin und her springen, was hohe Latenzen bedeutet, da es ein mechanischer vorgang ist.

Beim Schreiben auf den Socket machst du es dann ähnlich. Bau dir ein kleines Eventsystem und wenn z.b. dann 128k von der HDD gelesen wurden, gib sie in einen Netzwerksendethread, der das gleiche umgekehrt macht.

Das ist die effizienteste Lösung aus Softwaresicht. Der Rest ist Hardwareproblematik auf die du keinen Einfluss hast.
Natürlich kannst du nun noch ZIPStreams nutzen, dann wird die Übertragung nochmal effizienter ... etc...


----------



## Empire Phoenix (13. Sep 2010)

Ja mti win7 muss ich dir recht geben abe xp ist immer noch weiter verbreitet, daher meine antwort.


----------



## Kr0e (13. Sep 2010)

Aber vergiss eines nicht! Wenn du mit Java Daten über TCP austauschst, dann nutzt du die Winsocks. 
Deine Kritik (Die bei <= XP berechtigt ist...), dass das Protokoll ineffizient sei, bezieht sich dann aber konkret auf die TCP Impl. von Windows und nicht auf diesen Dateitransferdialog. Womit man zum Schluss kommt, dass ein Kopiervorgang mit dem Dialog genauso "ineffizient" ist, wie eine Dateiübertragung mit Java. Das bei TCP-Paketverlust Win XP schlecht agiert, trifft dann acuh auf Java zu leider. Somit wäre der Test (Wie lange Windows zum Kopieren braucht) schon berechtigt!

Und am Rande... Paketverlust ist bei WLAN häufiger als Paketankunft  Errinnert mich iwie an Hermes


----------



## homer65 (14. Sep 2010)

Was imho etwas bringen könnte, wäre die Daten vor und nach der Übertragung zu komprimieren.
Ist die Frage, ob sich der Aufwand lohnt?


----------



## Kr0e (14. Sep 2010)

Hallo Homer65 schau mal in meinen vorletzten Post, ganz unten.....

Ja, komprimierung bringt definitiv was, aber bedenke, dass die CPU-Last erhöht wird. Bau am Besten ne FUnktion ein "WLAN-Betrieb (Komprimierung)".

Mit ZIP bekommst du (Je nach Datentyp), 50 % der Größe, bei Texten fast bis zu 80 %. Sprich Chatnachrichten könnten sich lohnen...


----------



## tulius (14. Sep 2010)

> PS: Aber jetzt mal abgesehen vom Netzwerk. Dein Code ist sowieso nicht der effizienteste, sonder neine Standardlösung aus dem Lehrbuch =P. Wenn du effizient empfangen und senden willst, solltest du den Zugriff auf deine Festplatte nicht im selben Thread durchführen, wie den Zugriff aufs Netzwerk (Socket). Beides sind synch. IO-Operationen die jeweils relativ lange brauchen.
> 
> Am besten wäre ein "HardDiskThread" oder so, der aus einer Liste Buffers liest, die mit einer ID versehen sind und die dann in seinem Thread der Reihe nach auf die HD schreibt. Bei Festplatten solltest du außerdem einen größeren Puffer beim BufferedStream verwenden als 8192 kb (Standard beim BufferedStream) . 128k wären bei heutigen Festplatten schon eher vernüftig. Der Lesekopf muss sonst ständig hin und her springen, was hohe Latenzen bedeutet, da es ein mechanischer vorgang ist.
> 
> ...



Danke für den Tipp, werd ich mir mal anschauen.

Von Komprimierung halte ich nicht viel, denn es geht hier vor allem um die Übertragung großer Dateien und Ordner
Das sind typischerweise Dinge wie Bilder und Videos, die sind ja ohnehin schon komprimiert.
Ich hatte mal nen Zip-Stream reingehängt - hat nur die CPU hochgetrieben und kaum 1% gespart.


----------



## Kr0e (15. Sep 2010)

Ja, bei Mediendateien wurde alles rausgeholt, und für 1% hohe CPU-Lasten lohnt nicht.

Und wie gesagt: WLAN ist eher eine Zufallsübertragung als ein gut nutzbares Übertragungsystem. Pakete müssen andauernd neu angefordert werden. Die Antennen werden zu klein und zu billig gebaut und empfangen deshalb nur Mist.
Mein Vater hat mal eine selbst gebaut (Ist kein Witz!). Es gibt viele Bauanleitungen, ist granicht mal schwer und billig obendrein. Wenn solche Richtantennen korrekt ausgerichtet sind, sind 40-50 mbit in der Tat möglich. Sogar durch 2 Holzdecken hindurch (PC steht im Keller). Mit standard Antenne gab es kein Netzwerk  Die Technik ist heir noch in den Kinderschuhen... Liegt also nicht an deiner Software


----------



## maki (15. Sep 2010)

Guter Hinweis Kr0e!
WLAN-Richtfunk mit Hausmitteln | heise Netze


----------



## Kr0e (15. Sep 2010)

Gute Seite! Genau sowas meinte ich =)


----------

