Hallo, ja das habe ich schon ;-)
Naja, wenn ich so weiterlese dann muss ich dir sagen: Das ist kein Protokoll, das ist ein Zustand :-(
Ich habe ja probiert, die Datei auf Clientseite einfach mit einem BufferedInputReader auszulesen und mit einer while-Schleife Scheibchenweise mit einem Keyword am Anfang zu übertragen, welche dem Server erkenntlich macht, dass es sich um ein Dateistück zu DownloadID x handelt.
Das Problem ist nur, dass die Konvertierung des ausgelesenen Bytearrays zu String und zurück (vor und nach der Übertragung) scheinbar die Daten kaputt macht.
Jedenfalls werden Zeilenumbrüche scheinbar als Stringende betrachtet.
Falsch. Setzen. 6.
Sorry. Wenn du auf einem Stream verschiedene Datentypen verwenden willst, dann solltest du den DataInputStream und den DataOutputStream verwenden.
Auf beiden Seiten (Server und Client) solltest du einen Empfangs-Thread anlegen der eingehende Nachrichten auswertet und dann entscheidet was damit zu tun ist.
Eine Nachricht könnte wie folgt aussehen:
Header
1 byte: Typ der Nachricht. Mit einem Byte lassen sich 256 Nachrichtentypen abbilden.
1 Integer (das sind intern 4 bytes): Länge der restlichen Nachricht
Body
x bytes: die Restliche Nachricht, welche wiederumm in abhängigkeit des Nachrichtentyps aus verschiedenen primitoven/komplexen bestehen kann
Was du dann brauchst sind Nachrichten wie
1) "Server, bereite dich für den Empfang von Datei 1 namens XYZ vor"
2) "Server, hier kommt ein Teil der Datei 1"
3) "Server, ich beende mich jetzt"
4) "Client, dein gewünschter Dateitransfer 1 ist okay/nicht okay"
Nachricht 1) könnte wie folgt aufgebaut sein:
Header
1. byte: 0x00
Integer: 22 (komplette Länge des Bodys)
Body
Integer: 1 (Nummer/ID der Datei, wird später noch gebraucht, entspricht 4 bytes)
String: MyFile.ext (Name der Datei, entspricht 10 bytes)
long: 120000 (Die Datei hat soviele bytes ..., ein long ist 8 byte lang)
Und hier kommt Nachricht-Typ 2)
Header
1. byte: 0x01
Integer: 1028 (komplette Länge des Bodys)
Body
Integer: 1 (Nummer/ID der Datei, wird später noch gebraucht, entspricht 4 bytes)
byte[]: Ein erster Datenblock der Datei, z.B. 1024 bytes
Der Server hat ja mit der Nachricht vom Typ 0x00 schon mitbekommen wie lang die Datei ist und weiß wann er aufhören muss die Datei auf die Platte zu schreiben.
So, nun zu nachricht 3)
Header
1. byte: 0x02
Integer: 0 (komplette Länge des Bodys)
Body
kein body notwendig ... Dient ja nur der Signalisierung dass der Client nun weg ist..
Und Nachricht 4)
Header
1. byte: 0x03
Integer: 5 (komplette Länge des Bodys)
Body
Integer: 1 (Nummer/ID der betreffenden Datei, entspricht 4 bytes)
byte: 0x00 steht für OKAY, 0xFF steht für NICHT OKAY (entspricht 1 byte länge)
Mit diesen Nachrichten kannst du parallel mehrere Dateien gleichzeitig über eine Socketverbindung übertragen. DU hast zwar "etwas" overhead durch das Protokoll, aber das bisschen zusätzliche Last beim schrieben einen Datenpaketes (lediglich 12 bytes ...) fällt heutzutage absolut nicht ins Gewicht.
Weiterhin ist es ja so, dass der Client während er in der while-Schleife (die Dateistücken schickt) steckt, nicht auf Serverkommando's reagiert?
Wie gesagt. Mit einem vernünftigen Protokoll und je einem Thread pro Socket-Seite kannst du prüfen was für eine Nachtricht kommt und diese ggf. an andere Threads zur Verarbeitung/speicherung weiterleiten. Mit deinem bisheirgen Protokoll-Versuch geht das nicht wirklich. Das war/ist zu rudimentär.
Die Übertragungsgeschwindigkeit war damit auch mieserabel... ca. 2kb/s von localhost zu localhost ;-)
Naja, man sollte ja auch nciht versuchen Dateien als Strings zu übertragen. Wenn du den Versuch abgeschafft hast wirst du sehen das es schon ziemlich schnell geht. Schneller als deine Internetverbindung es zulässt. Und wenn du den Nagle-Algo auf dem Socket noch abschaltest, den Puffer entsprechend setzt und die Datenpakete die dazu passende Größe haben wirst du auch ein 100mbit Netzwerk gut ausgelastet bekommen.
- Alex