Fehler bei Datenübertagung (TCP/IP)



  • Hallo !

    Ich habe ein Server/Client Programm, Server in Java, Client in C.

    Die Kommunikation klappt wunderbar, bis auf ein Problem bei der Datenübertragung.

    Sende ich z.b vom Server eine größere Datei (~3 MB) an den Client, werden nicht alle Daten empfangen, und der client hängt in der recv() Funktion. Dieser Fehler tritt aber nicht immer auf !! Für Testzwecke habe ich auch 40 MB gesendet, manchmal kommen alle Daten an, manchmal nicht.

    Kann es sein das der Client in C nicht nachkommt mit dem Empfangen der Daten und so möglicherweise der internet Buffer fürs Empfangen von Daten überfüllt wird, und dabei Daten verloren gehen ??? Anders kann ich es mir nicht erklären, bei kleinen Daten funktioniert es wunderbar.

    Das Prinzip ist auch ganz primitiv und einfach, in einer Endlosschleife wird die recv() Funktion aufgerufen, sobald diese das Char-array, in welches die recv() Funktion schreibt, nicht komplett füllt, wird die Schleifen verlassen.

    Zusätzlich gibt es noch eine Abbruchbedingung, wenn nur 1 Byte empfangen wird, und dieser 0 ist, das ist notwending, falls die Dateigröße, die empfangen wird, genau ein Vielfaches der Char-array - größe ist, dann hängt der Sender einen 0-Byte an, ansonsten würde die recv()-Funktion wieder erneut aufgerufen.

    Hier der Code vom Client (bei der recv() Funktion bleibt er hängen) :

    for (;;) {
    
                        ivar = recv(socket_client,recvBuff,sizeof(recvBuff),0);
    
                 /*Die Abbruchbedingung, wenn nur mehr ein 0 Byte gesendet worden ist*/
                        if(ivar == 1 && recvBuff[0] == 0) {
                            fflush(file);
                            fclose(file);
                            break;
                        }
    
                        for (i = 0; i < ivar; i++) {
                            fputc(recvBuff[i],file);
                        }
    
                     /*Die 2. Abbruchbedingung, falls der Buffer, in den die recv() Funktion schreibt, nicht vollständig gefüllt wird*/
                        if (ivar != RECV_BUF_MAX) {
                            fflush(file);
                            fclose(file);
                            break;
                        }
    
                    }
    

    Ich hoffe ihr könnt mir weiterhelfen, ich sitze schon 2 Tage an diesem Problem.



  • statt "internet Buffer" meinte ich "interne Buffer"



  • Ich habe auch schon statt der fputc() Schleife versucht Blockweise die Daten in die File zu schreiben, falls jemand denkt, das diese Schleife zuviel Zeit kostet, daran liegt es nicht, glaube ich.



    Es kann immer vorkommen (auch wenn Du 40MB sendest), dass ein Packet mit 1 Byte kommt (und wenn da dann noch 0 drinsteht.. adios...).

    if(ivar == 1 && recvBuff[0] == 0) {
                            fflush(file);
                            fclose(file);
                            break;
                        }
    

    Deshalb kannst Du das nicht als Abbruchkriterium nehmen.

    Wenn der return Wert von recv() 0 ist, dann wurde die Verbindung geschlossen.
    (Sollte mindestens darauf reagiert werden.)

    Wenn ich das korrekt interpretiere, gibt es keine Abbruchbedingung für das ende der Übertragung.
    (Du könntest z.B. zuerst die Länge übertragen...)

    Gruss Simon



  • Wenn der Server RECV_BUF_MAX-Bytes sendet, ist nicht garantiert, daß sie beim Clienten als "Ganzes" ankommen.
    Durchaus möglich, daß der Client recv mehrmals aufrufen muß um auf RECV_BUF_MAX zu kommen.
    Aber dann springt er aus der Schleife wegen "ivar != RECV_BUF_MAX" und Bytes gehen verloren.



  • ,.,.,,.,. schrieb:

    /*Die 2. Abbruchbedingung, falls der Buffer, in den die recv() Funktion schreibt, nicht vollständig gefüllt wird*/
    if (ivar != RECV_BUF_MAX) {
    fflush(file);
    fclose(file);
    break;
    }

    }[/cpp]

    Hi !
    Die 2. Abbruchbedingung kannst du rausschmeissen. Niemand garantiert dir, das der Server immer RECV_BUF_MAX Byte in den Puffer schreibt.
    Ebenso kannst du überall das 'fflush(file)' rausschmeissen.

    Anstatt mit fputc kannst du effektiver mit fwrite schreiben:

    if ( ivar != fwrite( recvBuff, sizeof(char), ivar, file ))
    {
    // Fehlerbehandlung.
    }
    

    Der Erfolg der Übertragung hängt noch davon ab, wie du deine Ausgabedatei geöffnet hast, ob im Binär- oder Textmodus. Bei Windows zumindest musst du die Ausgabedatei mit fopen( ..., "wb" ) öffnen.
    🙂



  • Danke, ich habe auch schon daran gedacht zuerst Informationen über die Größe etc. zu senden.

    Was ich jedoch nicht gewusst habe ist, dass es auch möglich sein kann, das ein Packet mit einem einzigen 0 Byte gesendet wird ?!?!

    Ich dachte es wird zuerst immer das Array gefüllt, mit 512 Byte, aber wenn das so ist, dann ist mir jetzt einiges klar. Bei *.txt Datein ging die Übertragung nämlich immer Reibungslos, das lag dann wohl daran, das es in Text-datein keine 0 Bytes gibt.

    Zu deinen Punkt 3.

    Die Abbruchbedingung habe ich so gewählt, dass wenn das Array nicht komplett gefüllt wird, abgebrochen wird, jetzt weiß ich aber auch das es Falsch ist, und zu Problemen führen kann.

    Danke für deine Hilfe !!! 🙂 🙂

    Ich hoffe es klappt so.



  • Sry die Antwort ober mir wurde erst jetzt abgeschickt.

    Danke für die Hilfe !! Ich dachte bis jetzt immer das die Funktion recv() _immer_ den Buffer komplett befüllt.

    Danke vielmals!! 🙂



  • Hättest du mal die Dokumentation gelesen....


Anmelden zum Antworten