Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
TCP - Paket kommt nur teilweise an
bl8ckdr8gon
myCSharp.de - Member



Dabei seit:
Beiträge: 4

Themenstarter:

TCP - Paket kommt nur teilweise an

beantworten | zitieren | melden

Hallo! Zu allererst bin ich neu hier im Forum, ich freue mich eure Bekanntschaft zu machen :)
Ich hab mich mal dran gemacht einen Chatserver zu programmieren, welches natürlich Text aber auch Bilder übertragen soll. Text funktioniert reibungslos, jedoch scheint es bei Bildern große Probleme zu geben.

Zum Problem: Die Pakete werden ordungsgemäß gesendet, ebenso die Gesamtgröße des Byte Arrays, das Senden der Datei vom Client zum Server wird ebenfalls eingeleitet. Das Problem besteht hierbei darin, das beim Lesen der Verbindung plötzlich keine Daten mehr zur Verfügung stehen, der Client aber alles fleißig sendet. Jedoch, sobald der Client die Verbindung trennt, springt der Code im Server wieder an und liest weiter (da scheinbar wieder Daten vorhanden sind.), jedoch wirft der Server dann eine Exception, da die Verbindung vom Clienten ja beendet wird:
Fehler
"System.IO.IOException" wurde aufgefangen.
HResult=-2146232800
Message=Von der Übertragungsverbindung können keine Daten gelesen werden: Eine bestehende Verbindung wurde softwaregesteuert
durch den Hostcomputer abgebrochen.
Source=System
StackTrace:
bei System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
bei tcp_server.Server.SendImage(String fileName) in c:\Users\bl8ckdr8gon\Desktop\ClassChat_Server\rpn_server\Program.cs:Zeile 560.
bei tcp_server.Server.ReceiveImage(NetworkStream broadcastStream, Int32 TotalLength, String fileArt) in c:\Users\bl8ckdr8gon\Desktop\ClassChat_Server\rpn_server\Program.cs:Zeile 542.
bei tcp_server.Server.handleClinet.doChat() in c:\Users\bl8ckdr8gon\Desktop\ClassChat_Server\rpn_server\Program.cs:Zeile 651.
InnerException: System.Net.Sockets.SocketException
HResult=-2147467259
Message=Eine bestehende Verbindung wurde softwaregesteuert
durch den Hostcomputer abgebrochen
Source=System
ErrorCode=10053
NativeErrorCode=10053
StackTrace:
bei System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
bei System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
InnerException:

Nun die Frage: Was kann ich tun, um dieses Problem zu beheben? Ich habe schon ausprobiert ein TimeOut im Receive zu setzen, jedoch führte das zu noch mehr Problemen.

Im Anschluss noch die Ausschnitte aus dem Code.
Client (Senden) :


public void SendImage(string fileName)
{  
    byte[] SendingBuffer = null;  
    clientStream = client.GetStream();  
    FileStream Fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);  
    int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Fs.Length) / Convert.ToDouble(1024)));  
    int TotalLength = (int)Fs.Length, CurrentPacketLength;  
    for (int i = 0; i < NoOfPackets; i++)  
    {  
            if (TotalLength > 1024)  
            {  
                CurrentPacketLength = 1024;  
                TotalLength = TotalLength - CurrentPacketLength;  
            }  
            else  
                CurrentPacketLength = TotalLength;  
            SendingBuffer = new byte[CurrentPacketLength];  
            Fs.Read(SendingBuffer, 0, CurrentPacketLength);  
            //clientStream.WriteTimeout = 200;  
            clientStream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);  
    }  
clientStream.Flush();  
Fs.Close();  
}

Server (Empfangen) :


public void ReceiveImage(NetworkStream broadcastStream, int TotalLength, string fileArt = ".jpg")
{
    string fileName = id + fileArt;
    byte[] RecData = new byte[1024];
    int RecBytes = 0;
    int restBytes = TotalLength;

    int totalrecbytes = 0;
    FileStream Fs = new FileStream(Environment.CurrentDirectory + "\\ServerConfig\\" + fileName, FileMode.OpenOrCreate, FileAccess.Write);
    int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(TotalLength) / Convert.ToDouble(1024)));

    for (int i = 0; i < NoOfPackets; i++)
    {
        Fs.Write(RecData, 0, RecBytes);
        totalrecbytes += RecBytes;
        //Nur zu Testzwecken
        Console.WriteLine("Bytes left: " + RecBytes);
    }
    broadcastStream.Flush();
    Fs.Close();
    //Hier wird allen Clienten mitgeteilt das ein Bild gesendet wird
    broadcast("!~!IMAGE_INCOMING(" + fileArt + ")[" + TotalLength + "]!~!", "", false);
    //Nur zu Testzwecken
    Console.WriteLine("Beginning sending the image...");
    SendImage(fileName);
}

Ich freue mich auf Hinweise, Tipps,... von euch. Danke schon mal im Vorraus :)
mfg bl8ck
private Nachricht | Beiträge des Benutzers
TTopsecret
myCSharp.de - Member



Dabei seit:
Beiträge: 34

beantworten | zitieren | melden

Wo liest du überhaupt den broadcastStream auf der Serverseite?

Gruss
private Nachricht | Beiträge des Benutzers
bl8ckdr8gon
myCSharp.de - Member



Dabei seit:
Beiträge: 4

Themenstarter:

beantworten | zitieren | melden

Der broadcastStream wird an die Methode übergeben. :)
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4175

beantworten | zitieren | melden

Hallo,

und schon wieder mal der (anscheinend sehr beliebte) Fehler bei


Fs.Read(SendingBuffer, 0, CurrentPacketLength);
clientStream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);
Du darfst nur soviel senden, wie du auch gelesen hast (d.h. den Rückgabewert von Read nehmen), s. a. TCP Datenverlust beim Versenden über WAN
private Nachricht | Beiträge des Benutzers
TTopsecret
myCSharp.de - Member



Dabei seit:
Beiträge: 34

beantworten | zitieren | melden

Übergeben reicht nicht, gelesen sollte der NetworkStream auch noch werden. RecData wird zur Zeit nie einen Wert zugewiesen, obwohl der eigentlich die Daten aus dem Stream erhalten sollte. Zudem kommt das Problem von Th69 noch dazu

broadcastStream.Read(RecData, 0, RecBytes);

Gruss
private Nachricht | Beiträge des Benutzers
bl8ckdr8gon
myCSharp.de - Member



Dabei seit:
Beiträge: 4

Themenstarter:

beantworten | zitieren | melden

Zitat
Du darfst nur soviel senden, wie du auch gelesen hast (d.h. den Rückgabewert von Read nehmen)

Hab ich ausgebessert, jedoch ändert das leider nicht die Tatsache das der Server beim letzten Paket den Wert "DataAvaible" im broadcastStream auf false setzt
Dennoch Danke für den Hinweis

EDIT: Doch funktioniert, hatte nur an den falschen Stellen den Code bearbeitet
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von bl8ckdr8gon am .
private Nachricht | Beiträge des Benutzers
unconnected
myCSharp.de - Member

Avatar #avatar-3200.jpg


Dabei seit:
Beiträge: 862
Herkunft: Oerlinghausen/NRW

beantworten | zitieren | melden

Hallo, Du schliesst clientStream nicht. -> using verwenden, dann passiert das nicht.
private Nachricht | Beiträge des Benutzers
bl8ckdr8gon
myCSharp.de - Member



Dabei seit:
Beiträge: 4

Themenstarter:

beantworten | zitieren | melden

Das ist meine Absicht das der clientStream nicht geschlossen wird (sobald dieser geschlossen wird muss der Benutzer sich neu verbinden, hier geht es um einen Chatserver bei dem der Benutzer sich halt nicht ständig neu verbinden muss)
private Nachricht | Beiträge des Benutzers