socket: binare datei senden - beschleunigen



  • ich hoffe ich bin hier richig wenn nicht dann verbannt
    mit in ein anderes "thema" 🙂

    also ich möchte binare dateien über ein socketprogram versenden!
    ich tuhe dies mit diesem beispiel:

    #include <stdio.h>
    #include <windows.h>
    
    int main() {
    
    FILE *stream1;
    FILE *stream2;
    int ch;
    
    if((stream1 = fopen("c:\\lol.mp3","rb"))==NULL) {
    printf("fehler bei 1!\n");
    exit(1);
    }
    
    if((stream2 = fopen("c:\\lol2.mp3","wb"))==NULL) {
    printf("fehler bei 2!\n");
    exit(1);
    }
    
    ch=fgetc(stream1);
    
    while(!feof(stream1)) {
    fputc(ch,stream2);
    ch=fgetc(stream1);
    }
    
    fclose(stream1);
    
    }
    

    nur das der server halt sendet und der client empfängt und wieder in
    eine datei schreibt.

    so:
    while(ende) {
    server liest ch aus datei
    server sendet ch
    server wartet auf antowort von client
    client empfängt ch
    client schreibt ch in datei
    client sendet antwort
    }

    es klappt - nur leider dauert es SEHR lange 😞
    nun die eigentliche frage: wie kann ich dies beschleunigen?

    ich denke es leigt daran, das ich immer nur 1 byte versende 🙂

    wenn ich es so machen würde:

    ...
      ifstream in_file("c:\\lol.mp3", ios::in | ios::binary);
      ofstream out_file("c:\\lol2.mp3", ios::out | ios::binary); 
      string text; 
      while(!in_file.eof()) 
      { 
          getline(in_file, text);
          out_file << text << endl;  
    
      }
    in_file.close();
    out_file.close();
    ...
    

    und dann die strings versenden würde, würde es doch schneller gehen oder?

    mit

    string str; 
    send(s, str.c_str(), static_cast<int>(str.size()) + 1, 0);
    

    senden aber dann wie empfangen?

    ich kenne mich in diesem thema noch nicht so sehr aus also klärt
    mich auf falls ich was falsch mache 🙂

    danke schonmal!



  • hi, kannst du mal den ges. code zeigen mittn versenden!?

    cu



  • Lies am besten immer 1024 Bytes aus der Datei und sende diese. So ungefähr:

    char buf[1024];
    stream.read(buf, sizeof(buf));
    send(sock, buf, stream.gcount());
    

    Der empfänger bekommt dann ja über recv() mitgeteilt, wieviel Bytes gelesen wurden.

    1024, also 1k nehme ich immer, weils ne runde Zahl ist. Keine Ahnung wie der optimale Wert ist, aber besser als 1 Byte ist es.



  • hmm ich wollte so 1024 bytes auslesen, er nimmt aber keine leerzeichen
    das ist nicht gut oder? kann ja dann auch nicht mit binary klappen?!

    fstream in_file("c:\\bwt.txt", ios::in); 
    
      char text[1024]; 
    
      while(in_file >> text) 
      { 
        if(!in_file.eof()) 
        { 
          cout << text<<endl; 
          { 
          } 
        }
    

    also müsste ich einfach nur 1024b auslesen und diese dann rüber senden?
    mit recv einfach so annehmen?`

    char buf[1024];
    recv(sock,buf,1024,0);
    


  • babelduo schrieb:

    hmm ich wollte so 1024 bytes auslesen, er nimmt aber keine leerzeichen

    du liest auch anders ein, als ich. Benutz die read()-Methode.

    also müsste ich einfach nur 1024b auslesen und diese dann rüber senden?
    mit recv einfach so annehmen?`

    char buf[1024];
    recv(sock,buf,1024,0);
    

    Ja, aber denk dran, dass irgendwann vermutlich weniger als 1024 rauskommt, ausser die Datei ist genau ein Vielfaches von 1024 groß. Also den Rückgabewert von recv() auswerten.



  • hmm ok tut mir leid wenn ich nochmal nachfragen muss 😕

    wie meinst du das mit read() aus der datei lesen?

    und wie mache ich das, das buf immer so groß ist wie die bytes
    die gesendet wurden? so muss es doch sein oder?



  • hmm ich habe nochmal ein bischen nachgedacht und habe mir das hier
    zusammengefriemelt:

    #include <iostream> 
    #include <string> 
    #include <fstream> 
    
    using namespace std; 
    
    int main() 
    { 
    
    char buf[1024]; 
    
      ifstream in_file("c:\\lol.mp3", ios::in | ios::binary);
      ofstream out_file("c:\\lol2.mp3", ios::out | ios::binary); 
      while(!in_file.eof()) 
      { 
          //getline(in_file, text);
    
    in_file.read(buf, sizeof(buf)); 
    
          out_file << buf << endl;  
    
      }
    in_file.close();
    out_file.close();
    
    }
    

    nur leider ist lol.mp3 "1.313kb" groß und lol2.mp3 nur "0.131kb"
    was mache ich falsch?

    die farge mit recv von oben gilt noch 😉



  • bitte meckert mich nicht an oder so 😕 aber es ist 1.14 und ich
    habe schon sehr viel kaffee getrunken <-- habe frei!

    nun habe ich es so geschafft:

    #include <iostream> 
    #include <string> 
    #include <fstream> 
    
    using namespace std; 
    
    int main() 
    { 
    
    char buf[1024]; 
    
      ifstream in_file("c:\\lol.mp3", ios::in | ios::binary);
      ofstream out_file("c:\\lol2.mp3", ios::out | ios::binary); 
      while(!in_file.eof()) 
      { 
          //getline(in_file, text);
    
    in_file.read(buf, sizeof(buf));
    
          //out_file << buf << endl;
    
    out_file.write(buf, sizeof(buf));
    
      }
    in_file.close();
    out_file.close();
    
    }
    

    aber wie genau muss ich das denn nun bei recv machen?`
    ich geh nun oder versuche nun mal schlafen zu gehen 😛
    txh schonmal bis hier hin!



  • hallo!
    du solltest ja x mal 1024b auslesen, do gross halt die datei ist, oder hab ich das falsch verstanden!?

    lg



  • sorry machst du e;-) aber was ist wenn die datei kleiner als 1024b ist? oder 10000b ist? hm...

    lg



  • ja, ich habe ja schon ein Beispiel gepostet. Mit infile.gcount() bekommt man raus, wieviel gelesen wurde und mehr sollte man auch nicht senden.



  • hmm nehmen wir mal an die datei ist größer als 1024 😃

    also wenn cih zum senden dies hier benutze:

    send(s, buf, in_file.gcount());
    

    kommt ein fehler beim kompilieren:

    Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
    tc.cpp:
    Error E2193 tc.cpp 93: Too few parameters in call to '__stdcall send(unsigned in
    t,const char *,int,int)' in function main()
    *** 1 errors in Compile ***
    

    und wie müsste ich es dann mit recv annehmen?
    bei recv(sock,buf,1024,0); kann es ja sein das weniger als 1024 kommen,
    wie müsste ich das denn dann machen?



  • du hast da einen parameter vergessen, deshalb hast du einen error
    schau dir mal das an:

    send:

    int send (  SOCKET s, const char FAR * buf, int len, int flags );
    

    -s: Socket über den wir die Daten senden wollen
    -buf: Pointer auf einen Buffer in dem die zu sendenden Daten enthalten sind
    -len: Wieviele Bytes von buf gesendet werden sollen
    -flags: Brauchen wir nicht

    Rückgabewert: Anzahl der gesendeten Bytes oder SOCKET_ERROR bei einem Fehler.

    recv:

    int recv (  SOCKET s, char FAR* buf, int len, int flags );
    

    -s: Socket über den wir Daten empfangen wollen
    -buf: Pointer zu einem Buffer in dem die empfangenen Daten gespeichert werden sollen
    -len: Grösse des Buffers (oder wieviele Daten im Buffer gespeichert werden sollen)
    -flags: benötigen wir nicht

    Rückgabewert: Anzahl der empfangenen Bytes, 0 falls die Verbindung vom Partner getrennt wurde oder SOCKET_ERROR bei einem Fehler.



  • long rc;
    
    rc=recv(s,buf,1024,0);
    

    Hier werden maximal 1024 Zeichen empfangen, es können auch weniger empfangen werden, bei recv dient der dritte Parameter nur dazu die grösse des Buffers im zweiten Parameter anzugeben. Wieviele Zeichen wirklich empfangen wurden sieht man im Rückgabewert (in diesem Falle rc)!!

    also dann schaust du einfach: wie viele zeichen sind in rc, würd ich mal sagn!!
    oder was meint ihr?

    cu



  • wow 🙂 ok also bis jetzt klappt alles super!

    aber was muss ich noch tun wenn die datei die gesendet werden soll
    kleiner als 1024b ist? wenn ich so (nicht binar) eine txt-datei
    mit dem inhalt "hallo dies ist ein test" versenden will, steht
    nacher das hier drin:

    hallo dies ist ein test û Æ2@ @û *{ Xû '·@ ôtA ìú     *{ Xû     ¼wA °þ ù¦@ ¨0{ ¨0{ °þ *{ 46@ *{ |û ­H@ ÀtA X){ œ({ ÌtA µ7@ ÌtA     ˜û '·@ œwA @û  ü ô2@  ü ¨û '·@ ütA pû     û *{         Ìû Æ2@  ü *{ 8ü '·@ >èw¸  
       Ðû pèw¸  ø«A     çÝ0     “      ÿÿÿÿÿÿÿ       ,   <1{ ü  (@ ,   ø«A $ü <1{ ø«A hü šý@ §A     0   X){ <1{ _é@    ,1{     ¨0{ ­A ý '·@ $bA <ü        È){     xü ÉA  { X){ (ý Ù¡@    X){ ¨0{ ¨0{ ,   <1{ ¤ü  (@ ,   ø«A Äü <1{ ø«A ý šý@ §A     0   ,1{ <1{ _é@ &1{ ¨0{  ý     LC_M ý øü ´&@ ,1{ ý Ñ@ ,1{ ý 4@ ,1{ ý D@ ,1{ ,ý ?¢@ ,1{ [   ¨ý È–@  ý    ¨0{ ¨†A °þ     7  ÆŒw    Z   z   lý @    Ìý '·@  ‹A <ý    |({ °þzZ    '·@ ÀŠA xý X){ „ý    ,1{ øý  ¬@ ¨0{ °þ °þ ¨0{ |({ (þ     (þ '·@ T‘A ¸ý         8      øý y3@     Xþ Ù«@ °þ ¨0{ ¨†A <þ Vg@ |({ Pþ '·@ āA þ    '·@ ‘A     °þ lþ Vg@ |({ €þ '·@ āA Hþ    |({        àþ @    ½A ¼þ '·@ ôaA pþ     |({        ¨þ ÜQ@ ¨0{ äþ ¸Q@ àþ     ‹A ½A ÿ '·@ zA
    

    ich schreibe mit "out_file.write(buf,sizeof(buf));" wieder in die datei,
    habs mit out_file.write(buf,rc); versucht, beim binaren senden einer mp3
    klappt es, aber bei unbinaren senden der txt steht nacher nichts in der txt!



  • hmm ok, ich würde dann überprüfen ob die datei kleiner als 1024
    ist, und wenn dann würde ich buf so groß machen wie die datei ist.

    wenn ich die dateigröße in der int x gespeichert habe wie kann
    ich buf dann als größe x übergeben?

    int x=28;
    char buf[x];
    

    klappt leider nciht 😕



  • senden:

    ich würds so machen:

    [/cpp]
    char buf[1024];

    ifstream in_file("c:\\lol.mp3", ios::in | ios::binary);

    while(!in_file.eof())
    {
    in_file.read(buf, sizeof(buf));
    send(sock, buf, stream.gcount(), 0); // Mit infile.gcount() bekommt man raus, wieviel gelesen wurde zb.: kleiner als 1024, dieser parameter sagt ja wieviel zeichen vom buffer gesendet werden sollen!!!
    }

    in_file.close();
    [cpp]

    poste dann mal den fertigen code für senden u empfangen...

    cu



  • hmm ok - darf recv denn dann trotzdem so aussehen:

    rc=recv(connectedSocket,buf,1024,0);
    

    und auf 1024 warten?

    dann schreibe ich es mit

    out_file.write(buf,sizeof(buf));
    

    wieder in die datei

    mit

    send(s, buf, in_file.gcount(),0);
    

    sende ich

    und mit

    in_file.read(buf, sizeof(buf));
    

    lese ich aus der datei.

    aber es wird trotzdem mehr in die datei geschrieben als in_file.gcount()

    p.s: also in_file.gcount() ist in meinem fall genau 28, wenn ich aber

    in_file.read(buf, 28);
    

    anstatt

    in_file.read(buf, sizeof(buf));
    

    benutze ist die neue txt datei lehr 😕



  • i würd das so machen in etwa...
    is so ein grobentwurf....bitte @all um comments!!!

    cu

    typedef struct NETFILEHEADER
    {
        unsigned long FileSize;
        char pFileName[256];
    };
    
    //////////////// Senden ///////////////////////
    
    char buf[1024]; 
    
    // du solltest zuerst die dateigrösse zum client schicken...
    // am besten du machst eine structur aus dateinamen und dateigrösse und schickst das zum client!
    
    // Dateigrösse bestimmen:
    NETFILEHEADER FileHeader;
    in_file.seekg (0, ios::end);
    FileSize = in_file.tellg();
    in_file.seekg (0, ios::beg);
    
    // NetfileHeader setzten
    FileHeader.FileSize = FileSize;
    
    // Dateinamen bestimmen u dann in structur....musst selber probieren
    // dann den Fileheader zuerst an den client senden...u dann die datei...
    
    // Datei senden
    while(FileSize >= 1024)
    {
      in_file.read(buf, sizeof(buf));
      send(sock, buf, stream.gcount(), 0);   
      FileSize -= 1024;
    }
    
    // Ist Filesize kleiner als 1024
    if(FileSize)
    {
      in_file.read(buf, FileSize);
      send(sock, buffer, stream.gcount(), 0);
    }
    
    /////////////// Empfangen /////////////////////
    
    NETFILEHEADER FileHeader;
    char *FileHeader1 = new(char[sizeof(Netfileheader)];
    unsigned long AlreadyReceived = 0 
    unsigned long rc = 0;
    long FileSize;
    
    //Fileheader empfangen....
    do 
    { 
       rc = recv(client, Fileheader1, sizeof(NETFILEHEADER), 0); 
       AlreadyReceived += rc; 
       memcopy(FileHeader1, Netfileheader, rc);
    
    }while(AlreadyReceived<sizeof(NETFILEHEADER));
    
    FileSize = FileHeader.FileSize;
    
    // Dann öffnest du die datei 
    ofstream out_file (FileHeader.pFileName,ofstream::binary);
    
    // In Datei schreiben
    while(FileSize > 0)
    {
       rc = recv(client, buffer, 1024, 0);
       out_file.write(buf,sizeof(buf));
    
       FileSize -= rc;
    }
    
    //Datei schließen usw....
    


  • was sagst dazu?


Log in to reply