Kleines Problem beim Versenden von Datei über Sockets



  • Hallo,

    das hier bis jetzt mein erster Beitrag, weil ich es bisher geschafft habe im Forum eine Lösung auf eine Probleme zu finden. Aber diesmal weiß ich auch nicht weiter:

    Ich versende über ein Socket eine Datei ( z.b. ein Bild oder eine mp3-datei).
    Auf der anderen Seite kommt auf den Byte genau so viel an, wie viel ich verschickt habe( die gesamte Datei). Dennoch lässt sich das .jpg-Bild nicht öffnen, wahrscheinlich ist ein Fehler bei den letzten bytes.
    Die Lieder sind zu öffnen, aber die zusätzlichen Informationen ( Interpret usw. ) werden nicht mehr angezeigt.

    Daher meine Frage, kann es sein, dass man beim Schreiben in eine Datei zum Schluss noch was anhängen muss?

    Ich versende Buffer mit der Größe 1024, zum Schluss wird der verbleibene Rest in einem angepassten Buffer versendet, auf der anderen Seite wird natürlich dementsprechend empfangen.

    Ich hoffe, ihr habt eine Idee, was zu tun ist.

    M.f.g Sir.Wyver



  • Hm, merkwürdig, müsste eigentlich gehen 😕
    Wenn du dann die Original-Datei hast und die gesendete, unterscheiden die sich in der Größe? Oder guck dir einfach mal beide im Hex-Editor an (oder im MSVC++, Datei binär öffnen). Wahrscheinlich brauchste dir da nur Anfang und Ende angucken...
    Wenn bei der MP3-Datei der Interpret usw fehlt, müsste das ein Fehler am Anfang sein, dort stehen normalerweise die ID3-Tags. Viel Glück bei der Suche 🙂



  • zeig quellcode



  • Hi, auch daran gedacht, die ankommenden Daten zu Null-Terminieren.

    s=recv(socket,buffer,1024,0);
    buffer[s] = 0;
    


  • KasF schrieb:

    Hi, auch daran gedacht, die ankommenden Daten zu Null-Terminieren.

    s=recv(socket,buffer,1024,0);
    buffer[s] = 0;
    

    Weißt du eigentlich, wieviele Null-Bytes du in einer Mp3-Datei findest?...

    Edit: Wieso ist das Senden von Binär-Daten eigentlich so unpopulär? Gibt doch so viel mehr als nur Texte 😕



  • Badestrand schrieb:

    Weißt du eigentlich, wieviele Null-Bytes du in einer Mp3-Datei findest?...

    Was hat das mit meinem Code zu tun ???



  • Ok, erstmal vielen Dank für diese schnelle Beantwortung.
    Ich hab die beiden Datein im Hex-Editor verglichen und siehe da, am Anfang ist ein Fehler (nur Nullen). Das hilft mir schonmal ziemlich weiter, weil ich den Fehler immer am Ende vermutet hatte.
    Ich halt euch auf dem laufenden, wenn ich den (wahrscheinlich kleinen) Fehler gefunden habe.
    PS: Muss ich wirklich die Datei null-terminieren, denn die MP3-Datein gehen ja auch ohne?



  • SirWyver schrieb:

    Muss ich wirklich die Datei null-terminieren, denn die MP3-Datein gehen ja auch ohne?

    Nein, musst du nicht... Die gesendete Datei soll ja identisch sein, dazu gehört auch die Größen-Gleichheit 🙂

    KasF schrieb:

    Badestrand schrieb:

    Weißt du eigentlich, wieviele Null-Bytes du in einer Mp3-Datei findest?...

    Was hat das mit meinem Code zu tun ???

    Tschuldigung, ich wollte dir nix vorwerfen! Aber das Null-terminieren in deinem Code hat nur Sinn, wenn du Texte verschickst, nicht bei Binärdaten. Oder ich irre mich, dann musst du mich belehren 🤡



  • *Schnaarch* 🙂
    Hmm, ich denke mal das macht doch keinen Unterschied. Wenn er recv sagt dass er 1024 Daten lesen soll, dann kann es sein das mal beim lesen nur 500 gelesen werden und dann die restlichen 624 Bytes meines Array mit irgendwelchen Daten gefüllt sind. Deswegen muss geschaut werden wieviel mit recv gelesen wurde und da entsprechend Null terminieren.

    Es sei denn er passt darauf auf, wenn er in seine Datei schreibt.

    file.write(buffer,s); // s Zeichen schreiben, s returnwert von recv
    

    Ansonsten würde er ja wahrscheinlich ältere/ungültige Bytes reinschreiben.

    Badestrand schrieb:

    KasF schrieb:

    Badestrand schrieb:

    Weißt du eigentlich, wieviele Null-Bytes du in einer Mp3-Datei findest?...

    Was hat das mit meinem Code zu tun ???

    Tschuldigung, ich wollte dir nix vorwerfen!

    Auch sorry 🤡
    Dein Satz kam mir so provokant und angreifend vor, da musste ich genauso blöd zurück antworten.

    Aber kann sein das du auch Recht hast, denn am Ende werden die Dateien ehe über write geschrieben und für den gibts keine Null-Terminierung. Insofern sollte man als zweites Argument bei write den Return-Wert von recv angeben.

    Edit: Hast wahrscheinlich Recht, wenn er die Datei binär behandelt ...



  • Also, ich hab erstmal getestet, ob auch alles eingelesen wird, indem der Client aus den Daten, die er verschickt, selbst nochmal eine Datei erstellt. Diese funktioniert auch einwandfrei, daher muss wohl der fehler beim versenden liegen. Hierzu ein paar Quellcodeschnipsel:
    Der Client, der sendet:

    char buffer[10000];
      unsigned long int FileSize;
      int Status=0;
     FILE *datei;
    datei=fopen("C:\\kal.JPG","r+b");
    fseek(datei, 0, SEEK_END);
    FileSize = ftell(datei);
    fseek(datei, 0, SEEK_SET);
    string laenge;
    ostringstream outStream;
    outStream << FileSize;
    laenge = outStream.str();
    send(sock,laenge.c_str(),strlen(laenge.c_str()),NULL);
    
     if(datei)
        {
          while(!feof(datei)&&(Status<FileSize)&&(FileSize-Status>=1024))
          {
           fread(buffer,1024,1,datei);
           fwrite(buffer,1024,1,datei2);
           send(sock,buffer,1024,0);
           Status=Status+1024;
           cout<<endl<<Status<<"Bytes uebertragen"<<endl;
          }
    
      int klein=FileSize-Status;
      ostringstream outSe;
      outSe << klein;
      laenge = outSe.str();
      cout<<"Noch zu senden: "<<laenge;
    
      fread(buffer,klein,1,datei);
      send(sock,buffer,klein,0);
      Status=Status+klein;
      cout<<endl<<Status<<"Bytes uebertragen"<<endl;
      cout<<"Transfer beendet!"<<endl;
    
      fclose(datei);
    }
    

    Der Server, der empfängt:

    char buffer[1026];
          char laenge[1000];
          unsigned long int Status=0;
          cout<<"Datei senden"<<endl<<endl;
          recv(sockConnected,laenge,1001,NULL);
          unsigned long int FileSize;
          FileSize=atoi(laenge);
          cout<<endl<<"Größe: "<<FileSize;
          FILE *datei;
         datei=fopen("C:\\alfa.JPG","w+b");
         if(datei)
       {
          while(!feof(datei)&&(Status<FileSize)&&(FileSize-Status>=1024))
            {
              recv(sockConnected,buffer,1024,0);
              fwrite(buffer,1024,1,datei);
              Status=Status+1024;
              cout<<endl<<Status<<"Bytes uebertragen"<<endl;
            }
    
        int klein=FileSize-Status;
    
        recv(sockConnected,buffer,klein,0);
        fwrite(buffer,klein,1,datei);
        Status=Status+klein;
        cout<<endl<<Status<<"Bytes uebertragen"<<endl;
        cout<<"Transfer beendet!"<<endl;
        fclose(datei);
       }
    [cpp]  char buffer[10000];
      unsigned long int FileSize;
      int Status=0;
     FILE *datei;
    datei=fopen("C:\\kal.JPG","r+b");
    fseek(datei, 0, SEEK_END);
    FileSize = ftell(datei);
    fseek(datei, 0, SEEK_SET);
    string laenge;
    ostringstream outStream;
    outStream << FileSize;
    laenge = outStream.str();
    send(sock,laenge.c_str(),strlen(laenge.c_str()),NULL);
    
     if(datei)
        {
          while(!feof(datei)&&(Status<FileSize)&&(FileSize-Status>=1024))
          {
           fread(buffer,1024,1,datei);
           fwrite(buffer,1024,1,datei2);
           send(sock,buffer,1024,0);
           Status=Status+1024;
           cout<<endl<<Status<<"Bytes uebertragen"<<endl;
          }
    
      int klein=FileSize-Status;
      ostringstream outSe;
      outSe << klein;
      laenge = outSe.str();
      cout<<"Noch zu senden: "<<laenge;
    
      fread(buffer,klein,1,datei);
      send(sock,buffer,klein,0);
      Status=Status+klein;
      cout<<endl<<Status<<"Bytes uebertragen"<<endl;
      cout<<"Transfer beendet!"<<endl;
    
      fclose(datei);
    }
    

    M.f.G SirWyver



  • code mal deine schleife so das du keine sonderbehandlung für das letzte stück brauchst.



  • Das ist ziemlicher Müll den du da machst.
    Ließ dir das hier durch: http://www.cpp-tutor.de/cpp/le04/le04_03.htm und benutze einheitlich C++ Streams.



  • Ey du überprüfst ja gar nicht den Rückgabewert von recv!



  • Hi,
    ja ich weiß, ich bin noch ein ziemlicher Anfänger (halbes Jahr c++),
    Ich hab jetzt nochmal den Receive-rückgabewerte überprüft und es hat sich herausgestellt, dass er am Anfang oder am Ende (wenn er schon aus der Schleife raus ist) mal zu viel, mal zu wenig schickt. Wie kann ich das denn lösen, dass nicht mehrfach die gleichen Bytes geschickt werden oder dass er was weglässt?



  • Ich glaube der Rückgabewert von send gibt an, wieviele Bytes versendet wurden; können eben auch weniger sein als du wolltest - dann musst du den Rest halt noch mal schicken 🙂



  • Hallo,
    ich bräuchte nochmal Eure Hilfe. Ich hab jetzt die Schleife verbessert und beim ersten Senden macht er alles noch richtig, aber wenn man noch etwas versenden will, dann kommt eigentlich nur noch Mist heraus. Ich vermute, es hängt mit den Arrays zusammen, die ich verwende, dann die schon zum Teil gefüllt sind und dadurch was falsches verschickt wird.

    Hier nochmal mein Sender:

    void SendClient(SOCKET sock)
    {
      string Pfad;
      string Name;
      string tosend;
      FILE *datei;
      string laenge="0";
      unsigned long int FileSize;
      int gesendet;
    while(1)
    {
      cout<<"Welche Datei möchest Du verschicken?"<<endl;
      cout<<"Pfad: ";
      getline(cin,Pfad);
      cout<<"Name: ";
      getline(cin,Name);
      unsigned long int Status=0;
      tosend=Pfad+Name;
      send(sock,Name.c_str(),strlen(Name.c_str()),NULL);
      char buffer[10000];
      datei=fopen(tosend.c_str(),"r+b");
      if(!datei)
      {send(sock,laenge.c_str(),3,NULL);}
      else
      {
        fseek(datei, 0, SEEK_END);
        FileSize = ftell(datei);
        fseek(datei, 0, SEEK_SET);
        ostringstream outStream;
        outStream << FileSize;
        laenge = outStream.str();
        send(sock,laenge.c_str(),strlen(laenge.c_str()),NULL);
    
        while(!feof(datei)&&(FileSize>Status))
          {
           fread(buffer,1024,1,datei);
           gesendet=send(sock,buffer,1024,0);
           Status=Status+gesendet;
           }
        cout<<endl<<"Transfer beendet!"<<endl;
        fclose(datei);
      }
    }
    }
    

    Der Empfänger:

    void Receive(SOCKET sock)
    {
      string name="";
      char name1[1000];
      char laenge[1002];
      recv(sock,name1,1026,NULL);
      name=name1;
      cout<<"Name der Datei: "<<name<<endl;
      recv(sock,laenge,1001,NULL);
      cout<<"Groeße der Datei: "<<laenge<<endl;
      name="C:\\Downloads\\"+name;
      unsigned long int FileSize;
      unsigned long int Status=0;
      FileSize=atoi(laenge);
      if(FileSize!=0)
      {
         FILE *datei;
         datei=fopen(name.c_str(),"w+b");
         int empfangen;
         char buffer[10000];
         if(datei)
       {
          while(!feof(datei)&&(FileSize>Status))
            {
              empfangen=recv(sock,buffer,1024,0);
              fwrite(buffer,empfangen,1,datei);
              Status=Status+empfangen;
            }
        cout<<endl<<Status<<" Bytes uebertragen"<<endl;
        cout<<"Transfer beendet!"<<endl;
        fclose(datei);
       }
      }
    }
    

    Wäre echt nett, wenn Ihr mir helfen könntet 🙂
    Dann vielen Dank im Voraus!


Anmelden zum Antworten