Laden...

TCP - Paket kommt nur teilweise an

Erstellt von bl8ckdr8gon vor 9 Jahren Letzter Beitrag vor 9 Jahren 3.189 Views
B
bl8ckdr8gon Themenstarter:in
4 Beiträge seit 2014
vor 9 Jahren
TCP - Paket kommt nur teilweise an

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:> Fehlermeldung:

"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

T
34 Beiträge seit 2014
vor 9 Jahren

Wo liest du überhaupt den broadcastStream auf der Serverseite? 😉

Gruss

B
bl8ckdr8gon Themenstarter:in
4 Beiträge seit 2014
vor 9 Jahren

Der broadcastStream wird an die Methode übergeben. 😃

4.931 Beiträge seit 2008
vor 9 Jahren

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

T
34 Beiträge seit 2014
vor 9 Jahren

Ü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

B
bl8ckdr8gon Themenstarter:in
4 Beiträge seit 2014
vor 9 Jahren

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

849 Beiträge seit 2006
vor 9 Jahren

Hallo, Du schliesst clientStream nicht. -> using verwenden, dann passiert das nicht.

B
bl8ckdr8gon Themenstarter:in
4 Beiträge seit 2014
vor 9 Jahren

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)