Laden...

TCP Datenverlust beim Versenden über WAN

Erstellt von Chester vor 10 Jahren Letzter Beitrag vor 10 Jahren 2.158 Views
C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren
TCP Datenverlust beim Versenden über WAN

Hallo,
Ich versuche Dateien über TCP zu versenden. Alles klappt perfekt wenn ich es auf dem lokalen Computer mit der IP 127.0.0.1 versuche. Doch wenn ich es über WAN, also außerhalb meines Netzwerkes auf einen anderen Computer hin versuche, dann treten bei Dateien > 5KB große Datenverluste auf ( < 5KB klappt perfekt). Ich weiß nicht, woran das liegt, aber vielleicht kann mir hier ja jemand helfen...

Hier noch der Code zum Senden:


                            int BufferSize = 1024;
                            byte[] SendingBuffer = new byte[BufferSize];
                            progressBox pForm = new progressBox();
                            pForm.label1.Text = "Sending file to " + remotePCname + "...";
                            TcpListener tcpFileListener = new TcpListener(IPAddress.Any, 2729);
                            tcpFileListener.Start();
                            TcpClient fileClient = tcpFileListener.AcceptTcpClient();
                            FileStream fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read);
                            NetworkStream netstream = fileClient.GetStream();
                            int totalLength = (int)fileStream.Length;
                            pForm.progressBar1.Maximum = totalLength;
                            int totalSent = 0;
                            pForm.Show();
                            while (totalSent < totalLength)
                            {
                                totalSent += fileStream.Read(SendingBuffer, 0, BufferSize);
                                netstream.Write(SendingBuffer, 0, SendingBuffer.Length);

                                if (pForm.progressBar1.Value >= pForm.progressBar1.Maximum)
                                {
                                    pForm.progressBar1.Value = pForm.progressBar1.Minimum;
                                }
                                pForm.progressBar1.Value = totalSent;
                            }
                            netstream.Close();
                            tcpFileListener.Stop();
                            fileClient.Close();
                            fileStream.Close();
                            pForm.Close();

und zum Empfangen:


TcpListener tcpFileListener = new TcpListener(IPAddress.Any, 2729);
                tcpFileListener.Start();
                TcpClient fileClient = tcpFileListener.AcceptTcpClient();
                NetworkStream fileStream = fileClient.GetStream();
                FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
                progressBox pForm = new progressBox();
                pForm.label1.Text = "Receiving file from " + remotePCname + "...";
                pForm.progressBar1.Maximum = size;
                pForm.Show();

                byte[] currentRead = new byte[1024];
                int bytesRead;
                int totalRead = 0;

                while (totalRead < size)
                {
                    bytesRead = 0;
                    try
                    {
                        bytesRead = fileStream.Read(currentRead, 0, 1024);
                        fs.Write(currentRead, 0, currentRead.Length);

                        if (pForm.progressBar1.Value >= pForm.progressBar1.Maximum)
                        {
                            pForm.progressBar1.Value = pForm.progressBar1.Minimum;
                        }
                        pForm.progressBar1.PerformStep();
                    }
                    catch
                    {
                        break;
                    }
                    if (bytesRead == 0)
                    { break; }
                }
                tcpFileListener.Stop();
                fileStream.Close();
                fileClient.Close();
                fs.Close();
                pForm.Close();

Gruß,
Chester

2.298 Beiträge seit 2010
vor 10 Jahren

An dem Punkt, das der ganze Code eher suboptimal ist setze ich jetzt nicht an.

Woher kennt die Empfangsseite die "size"?

Es gibt die Available-Eigenschaft beim TcpClient, die dir angibt ob Daten zu lesen da sind und wann keine mehr da sind.

Zu deinem eigentlichen Fehler jedoch vermute ich, das eine Exception geworfen wird, die du durch dein break unterdrückst. -> Das Break beendet das Empfangen.

Wissen ist nicht alles. Man muss es auch anwenden können.

PS Fritz!Box API - TR-064 Schnittstelle | PS EventLogManager |

W
872 Beiträge seit 2005
vor 10 Jahren

Ich sehe direkt zwei Probleme:*TCP ist ein "hoefliches" Protokoll - d.h. der Sender darf sich nicht verabschieden, bevor die Kommunikation mit dem Empfaenger beendet ist. *Beim Senden wird kein Flush aufgerufen - erst nach dem Flush wird 100 % etwas verschickt.

4.939 Beiträge seit 2008
vor 10 Jahren

Hallo Chester,

ein weiterer Fehler ist bei


bytesRead = fileStream.Read(currentRead, 0, 1024);
fs.Write(currentRead, 0, currentRead.Length);

Du darfst nur soviel schreiben, wie du auch gelesen hast, also


fs.Write(currentRead, 0, bytesRead);

(Length gibt immer die statische Größe des (Byte-)Arrays zurück.)

PS: Der selbe Fehler ist auch bei der Senden-Methode...
PPS: Packe deinen Code in using-Blöcke anstatt manuell Close() aufzurufen.

4.221 Beiträge seit 2005
vor 10 Jahren

@Th69

Scheint ein beliebter Fehler zu sein 😃

Den hatten wir erst kürzlich schon mal hier: NetworkStream in Datei speichern + Fortschrittsanzeige des Downloads

Gruss
Programmierhans

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren

Vielen Dank für all die Hilfe von eurer Seite!
Es lag vermutlich wirklich daran, dass ich nicht die bytesRead beim Stream verwendet habe, und daran, dass das Flush() nach dem Schreiben in den Stream gefehlt hat.
Nun funktioniert alles wie gewollt. 🙂

Gruß,
Chester

C
Chester Themenstarter:in
25 Beiträge seit 2013
vor 10 Jahren

Wo soll ich den using-Block herum packen? Und wie soll der aussehen?

Hinweis von Coffeebean vor 10 Jahren

Hallo Chester,

jetzt gehts klar Richtung "Grundlagen". Bitte beachte [Hinweis] Wie poste ich richtig? Punkt 1.1 und 1.1.1.

5.658 Beiträge seit 2006
vor 10 Jahren

Weeks of programming can save you hours of planning