Laden...

Dateiübertragung per Sockets: Fehler beim Lesen der Daten

Erstellt von kudu vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.778 Views
K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren
Dateiübertragung per Sockets: Fehler beim Lesen der Daten

Nabend,

ich weiß, dies ist ein ziemlich klassisches Thema, aber die Forensuche brachte zu diesem Problem leider kein Ergebnis. Ich habe zwei simple Anwendungen: Einmal einen Client, der per Sockets die Verbindung zum Server herstellt und dann ein Bild sendet. Auf der anderen Seite wartet der Server auf eingehende Verbindungsanfragen und liest die übertragenen Daten.

Hier der Client:


        static void Main(string[] args)
        {

            Console.WriteLine("Send file using sockets:");
            Console.WriteLine("------------------------");
            Console.WriteLine();

            // Sockets initialisieren
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Parse("xx.xx.xx.xx."), 3003);
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);

            // Datei in den Speicher laden
            string filePath = @"C:\Users\Christian\Desktop\asdf.jpg";
            byte[] data = File.ReadAllBytes(filePath);
            Console.WriteLine("{0} loaded into memory ({1} bytes)", Path.GetFileName(filePath), data.Length);

            // Datenpaket vorbereiten
            byte[] dataLengthByte = BitConverter.GetBytes(data.Length);
            byte[] packet = new byte[4 + data.Length];
            dataLengthByte.CopyTo(packet, 0);
            data.CopyTo(packet, 4);
            Console.WriteLine("Packet created ({0} bytes overall)", packet.Length);

            // Verbinden
            try
            {
                clientSocket.Connect(ipEnd);
                Console.WriteLine("Socket connected to {0}", ipEnd.Address);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error connecting socket!");
                Console.WriteLine("## {0}", ex.Message);
            }

            // Daten senden
            try
            {
                int bytesSent = clientSocket.Send(packet);
                Console.WriteLine("{0} bytes sent", bytesSent);
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error sending data!");
                Console.WriteLine("## {0}", ex.Message);
            }

            // Socket schließen
            clientSocket.Close();
            Console.WriteLine("Connection closed");
            Console.ReadLine();

        }

Und der Server:


static void Main(string[] args)
        {

            // Sockets initialisieren
            IPEndPoint ipEnd = new IPEndPoint(IPAddress.Any, 3003);
            Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            serverSocket.Bind(ipEnd);

            // Auf Verbindungen warten
            Console.WriteLine("Server listening on port {0}", ipEnd.Port);
            serverSocket.Listen(100);
            Socket clientSocket = serverSocket.Accept();
            Console.WriteLine("Client connected: {0}", clientSocket.RemoteEndPoint);

            byte[] fileLengthByte = null;

            // Daten lesen
            try
            {
                fileLengthByte = new byte[4];
                int bytesRead = clientSocket.Receive(fileLengthByte);
                Console.WriteLine("{0} bytes read: {1}", bytesRead, BitConverter.ToInt32(fileLengthByte, 0));
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error reading from socket");
            }

            // Restl. Daten lesen
            try
            {
                byte[] data = new byte[BitConverter.ToInt32(fileLengthByte, 0)];

                int overallRead = 0;
                int bytesLeft = data.Length;

                while (bytesLeft > 0)
                {

                    int nextReadSize = (bytesLeft > 1024) ? 1024 : bytesLeft;

                    int bytesRead = clientSocket.Receive(data, overallRead, nextReadSize, SocketFlags.None);
                    Console.WriteLine("{0} bytes read, overall {1}", bytesRead,overallRead+bytesRead);
                    overallRead += bytesRead;
                    bytesLeft -= bytesRead;


                }

                // Auf Desktop speichern
                File.WriteAllBytes(@"C:\Users\Christian\Desktop\sock.jpg", data);
                Console.WriteLine("File saved to desktop");

            }
            catch (Exception ex)
            {
                Console.WriteLine("Error reading from socket");
            }

            Console.ReadLine();


        }

Wenn ich das ganze Programm in der lokalen Umgebung, also auf 127.0.0.1, laufen lasse, funktioniert das ganze korrekt und ich erhalte folgende Ausgabe vom Server:


Server listening on port 3003
Client connected: 127.0.0.1:56383
4 bytes read: 94239
1024 bytes read, overall 1024
1024 bytes read, overall 2048
1024 bytes read, overall 3072
1024 bytes read, overall 4096
1024 bytes read, overall 5120
1024 bytes read, overall 6144
1024 bytes read, overall 7168
1024 bytes read, overall 8192
1024 bytes read, overall 9216
1024 bytes read, overall 10240
1024 bytes read, overall 11264
1024 bytes read, overall 12288
1024 bytes read, overall 13312
1024 bytes read, overall 14336
1024 bytes read, overall 15360
1024 bytes read, overall 16384
1024 bytes read, overall 17408
1024 bytes read, overall 18432
1024 bytes read, overall 19456
1024 bytes read, overall 20480
1024 bytes read, overall 21504
1024 bytes read, overall 22528
1024 bytes read, overall 23552
1024 bytes read, overall 24576
1024 bytes read, overall 25600
1024 bytes read, overall 26624
1024 bytes read, overall 27648
1024 bytes read, overall 28672
1024 bytes read, overall 29696
1024 bytes read, overall 30720
1024 bytes read, overall 31744
1024 bytes read, overall 32768
1024 bytes read, overall 33792
1024 bytes read, overall 34816
1024 bytes read, overall 35840
1024 bytes read, overall 36864
1024 bytes read, overall 37888
1024 bytes read, overall 38912
1024 bytes read, overall 39936
1024 bytes read, overall 40960
1024 bytes read, overall 41984
1024 bytes read, overall 43008
1024 bytes read, overall 44032
1024 bytes read, overall 45056
1024 bytes read, overall 46080
1024 bytes read, overall 47104
1024 bytes read, overall 48128
1024 bytes read, overall 49152
1024 bytes read, overall 50176
1024 bytes read, overall 51200
1024 bytes read, overall 52224
1024 bytes read, overall 53248
1024 bytes read, overall 54272
1024 bytes read, overall 55296
1024 bytes read, overall 56320
1024 bytes read, overall 57344
1024 bytes read, overall 58368
1024 bytes read, overall 59392
1024 bytes read, overall 60416
1024 bytes read, overall 61440
1024 bytes read, overall 62464
1024 bytes read, overall 63488
1024 bytes read, overall 64512
1024 bytes read, overall 65536
1024 bytes read, overall 66560
1024 bytes read, overall 67584
1024 bytes read, overall 68608
1024 bytes read, overall 69632
1024 bytes read, overall 70656
1024 bytes read, overall 71680
1024 bytes read, overall 72704
1024 bytes read, overall 73728
1024 bytes read, overall 74752
1024 bytes read, overall 75776
1024 bytes read, overall 76800
1024 bytes read, overall 77824
1024 bytes read, overall 78848
1024 bytes read, overall 79872
1024 bytes read, overall 80896
1024 bytes read, overall 81920
1024 bytes read, overall 82944
1024 bytes read, overall 83968
1024 bytes read, overall 84992
1024 bytes read, overall 86016
1024 bytes read, overall 87040
1024 bytes read, overall 88064
1024 bytes read, overall 89088
1024 bytes read, overall 90112
1024 bytes read, overall 91136
1024 bytes read, overall 92160
1024 bytes read, overall 93184
1024 bytes read, overall 94208
31 bytes read, overall 94239
File saved to desktop

Wenn ich den Client jetzt so umstelle, dass die externe IP angesprochen werden soll, sieht das jedoch nur noch so aus:


Server listening on port 3003
Client connected: xx.xx.xx.xx:56389
4 bytes read: 94239
1024 bytes read, overall 1024
432 bytes read, overall 1456
Error reading from socket

Ich sitze jetzt schon den ganzen Tag an diesem Problem und finde einfach keinen Ausweg. Ein Einstellungsproblem vermute ich eigentlich nicht, immerhin wird die Größe des Bildes in den ersten vier Bytes ja richtig übertragen und auch vollständig gelesen. Warum blockiert Receive dann jedoch bereits nach 1456 Bytes? Was entgeht mir hier?

Bin dankbar für jeden Hinweis.

Gruß,
kudu

1.346 Beiträge seit 2008
vor 12 Jahren

Nimm den ProtocolType Tcp

K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren

Danke für den Tipp, hat jedoch leider keine Änderung bewirkt. Hätte mich auch gewundert, ich habe das eben testweise nochmal auf TcpClient Basis umgesetzt und habe das selbe Problem.

1.346 Beiträge seit 2008
vor 12 Jahren

Was tritt denn genau für eine Ausnahme auf?

K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren

Eine vorhandene Verbindung wurde vom Remotehost geschlossen

K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren

Ich habe das ganze auch nochmal über die UDPClient Klasse versucht, weil es so viel Spaß macht. Das Ergebnis ist jedoch das Selbe: Es werden zwar einige Daten gelesen (im Fall der Übertragung per UDP: 32kbit, entspricht einem gesendeten Paket), anschließend blockiert Receive jedoch bis zum Timeout - obwohl da nachweislich Daten zu lesen sein müssten, da WireShark die Pakete alle aufgelistet hat (sowohl die Gesendeten, als auch die Empfangenen).

W
872 Beiträge seit 2005
vor 12 Jahren

Wie in einem anderen Thread erklaert, haengt die TCP Paket Groesse vom MTU ab - ergo kannst Du keine Paketgroesse erwarten - Du musst lesen bis Du die Gesamtlaenge erhalten hast.
Es kann Dir passieren, dass Du halbvolle Pakete hast, aber danach noch mehr Pakete kommen.
So kann zum Beispiel auf TCP Ebene ein Paket 1500 Bytes lang sein, also bekommst Du dann 1024 und dann 432 und dann wieder 1024 + 432 - die 44 Byte dazwischen sind fuer TCP selbst.
TCP ist halt ein Stream und Du musst lesen, bis Du alles hast.
Der Client muss auch warten, bis der Server alles gelesen hast. Wie waere es, wenn Du eine FileReceived Message vom Server implementierst, die der Server schickt, nachdem alles empfangen ist und auf die der Client wartet, bis der Server fertig ist und erst dann den Socket schliesst?

K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren

Im Server-Code ist ja bereits implementiert, dass solange vom Stream gelesen werden soll, bis die Anzahl der zu erwartenden Bytes auch erreicht wurde, daran sollte es also nicht liegen. Auch wenn ich den Client noch auf eine Nachricht vom Server warten lasse, ist beim Server bereits nach 1456 Bytes schluss.

W
872 Beiträge seit 2005
vor 12 Jahren

Wie lautet denn die genaue Exception?

K
kudu Themenstarter:in
7 Beiträge seit 2012
vor 12 Jahren

Nach einer gefühlten Ewigkeit bekomme ich dies hier (obwohl der Client noch läuft und auf Antwort vom Server wartet):

Von der Übertragungsverbindung können keine Daten gelesen werden: Eine vorhandene Verbindung wurde vom Remotehost geschlossen.