C# Datei über Netzwerk senden: Datei kommt unvollständig/beschädigt an

Jack159

Lieutenant
Registriert
Dez. 2011
Beiträge
766
Ich sitze gerade an einem C#-Projekt, welches aus 2 Anwendungen besteht (Clientanwendung und Serveranwendung).
Der Client sendet eine beliebige Datei und der Server empfängt diese und speichert diese bei sich im Ordner ab.

Bisher sind mir 2 Probleme aufgefallen:

- Wenn der Client eine ~19MB große .txt Datei schickt, welche komplett voll mit zufälligen Zeichen ist (jedoch keinerlei Leerzeichen!), dann empfängt der Server zwar eine ~19MB große .txt Datei, jedoch stehen nur in den ersten paar Zeilen dieser .txt Datei Zeichen und die restlichen Zeilen sind komplett (fälschlicherweise) mit Leerzeichen befüllt (wo eigentlich ebenfalls irgendwelche Zeichen stehen müssten). Der Inhalt der .txt kommt also nicht vollständig an.

- Wenn der Client ein 9KB großes .png Bild schickt, dann kommt beim Server zwar auch eine 9KB großes .png Bilddatei an, jedoch lässt sich diese Bilddatei, welche der Server empfangen hat, nicht öffnen. Die Windows-Fotoanzeige zeigt die Meldung, dass die Datei entweder beschädigt oder zu groß sei...


Server:
Code:
public void recieveFile() {
    NetworkStream nws = clientconnection.GetStream();
    StreamReader sr = new StreamReader(nws);
    StreamWriter sw = new StreamWriter(nws);

    // Recieve filename
    string filename = sr.ReadLine().Remove(0, 10);

    // Recieve filesize
    long filesize = Convert.ToInt64(sr.ReadLine().Remove(0, 10));

    Byte[] fileBytes = new Byte[filesize];
    nws.Read(fileBytes, 0, fileBytes.Length);
    nws.Close();

    var a = File.OpenWrite(filename);
    a.Write(fileBytes, 0, fileBytes.Length);
    a.Flush();
    a.Close();
}


Client:

Code:
public void sendFileToServer(String filename) {
    var a = File.OpenRead(filename);

    FileInfo fo = new FileInfo(filename);
    long filesize = fo.Length;

    // Write file into fileBytes-Array
    Byte[] fileBytes = new Byte[filesize];
    a.Read(fileBytes, 0, fileBytes.Length);
    a.Close();

    // Send filename to server
    sw.WriteLine("Filename: " + filename);
    sw.Flush();

    // Send filesize to server
    sw.WriteLine("Filesize: " + filesize);
    sw.Flush();

    // Send fileBytes to server
    NetworkStream nws = clientConnection.GetStream();
    nws.Write(fileBytes, 0, fileBytes.Length);
    nws.Flush();
    nws.Close();

    sw.Close();
    sr.Close();
    clientConnection.Close();
}
 
Hi,

vor kurzem hatte ich ein ähnliches Problem, als ich eine Netzwerk Bibliothek für ein Multiplayer Spiel geschrieben habe.
Hier ist meine Vermutung:

Beim Server, wenn du die eigentliche Datei aus dem Stream holst:

Code:
nws.Read(fileBytes, 0, fileBytes.Length);

Hier liegt glaube ich ein verständnis Problem vor.
Mit dieser Zeile versuchst du so viele bytes aus dem Stream zu holen wie die
Datei groß ist.

Das Problem tritt auf, weil zu diesem Zeitpunkt noch nicht alle bytes vorhanden sind.
Deshalb erhälst du nur die Anzahl an bytes, die bereits im Puffer sind, der rest geht
verloren.

Hier ist mein Vorschlag, wie das Problem zu lösen sein müsste:

Code:
int size = filesize;
byte[] fileBytes = null;

using (MemoryStream ms = new MemoryStream())
{
    while (size > 0)
    {
        byte[] buffer = new byte[size];
        int received = this.stream.Read(buffer, 0, size);
        ms.Write(buffer, 0, received);
        size -= received;
    }
    fileBytes = ms.ToArray();
}

Bei diesem Code wird solange aus dem Stream gelesen, bis
alle bytes der Datei übertragen wurden.

Viel Erfolg.
MfG T2xlc
 
@ T2xlc:

Danke, jetzt funktionierts. Ich habe deinen Vorschlag bei mir eingebaut:

Client:

Code:
            Byte[] fileBytes = new Byte[1024];
            long count = filesize;
            while (count > 0) {
                int recieved = a.Read(fileBytes, 0, fileBytes.Length);
                a.Flush();
                nws.Write(fileBytes, 0, recieved);
                nws.Flush();
                count -= recieved;
            }

Server:

Code:
            long count = filesize;
            Byte[] fileBytes = new Byte[1024];
            var a = File.OpenWrite(filename);
            while (count > 0) {
                int recieved = nws.Read(fileBytes, 0, fileBytes.Length);
                nws.Flush();
                a.Write(fileBytes, 0, recieved);
                a.Flush();
                count -= recieved;
            }
 
Hier stand mist
 
Zuletzt bearbeitet: (Hier stand mist)
Zurück
Oben