Datei binär kopieren



  • Hey liebes Forum, ich arbeite an einem kleinen Administrator tool für mein Heimnetzwerk.
    Nun möchte ich eine Dateiübertragung über das LAN machen und da cpoy () sicher nicht geht möchte ich die Datei binär einlesen und stückchenweise diese Daten an den Zielcomputer senden, wo mein Programm den ganzen Kram wieder entschlüsselt und die Datei wiederherstellt. Ich habe schon

    ifstream is;
    is.open ("C:\\meinProgramm.exe", ios_base::binary );
    

    ausprobiert, aber da kommt nur Mist bei rum.
    Vielen Dank schon einmal im Voraus.


  • Mod

    DerCoder schrieb:

    aber da kommt nur Mist bei rum.

    Soso. Dann liegt doch glasklar auf der Hand wo der Fehler liegt. Ist doch total offensichtlich.



  • 🙂 Ich frage nicht, wo mein Fehler liegt, sondern nach einem Ansatz für eine Lösung. Ein einfacher Funke Idee reich mir volkommen...


  • Mod

    DerCoder schrieb:

    🙂 Ich frage nicht, wo mein Fehler liegt, sondern nach einem Ansatz für eine Lösung. Ein einfacher Funke Idee reich mir volkommen...

    Mehr als ios::binary kann man da auch nicht sagen, wenn es um das binäre Lesen von Dateien geht. Willst du noch gezeigt bekommen, wie der eigentliche Auslesevorgang abläuft? Eigentlich genauso wie sonst auch, nur dass man dann eben Datentypen verwendet, die für binäres Lesen geeignet sind.



  • Was ich mich frage ist, ob das ganze Prozedere auch funktioniert:
    - Der Client sendet die Anfrage auf das Kopieren der Datei.
    - Daraufhin sendet der Server eine Antwort, zb "ok".
    - Der Client sendet dann den Dateinamen und dann Zeichen für Zeichen die Datei.


  • Mod

    DerCoder schrieb:

    Was ich mich frage ist, ob das ganze Prozedere auch funktioniert:
    - Der Client sendet die Anfrage auf das Kopieren der Datei.
    - Daraufhin sendet der Server eine Antwort, zb "ok".
    - Der Client sendet dann den Dateinamen und dann Zeichen für Zeichen die Datei.

    Das klingt nach einem guten Konzept, das auch funktionieren wird. Vielleicht noch die Pakete etwas größer machen als 1 Zeichen, um Overhead zu verringern. Und du musst natürlich ein Protokoll verwenden, bei dem sichergestellt ist, dass die Pakete hinterher in der richtigen Reihenfolge zusammengesetzt werden.



  • Ja, das ganze soll über TCP/IP laufen. Kann ich das nicht einfach so machen, das ich jedes Zeichen als Ascii wert übermittle? Ja, es würde ziemlich lange dauern, aber rein theoretisch...
    Oder hast du eine besser Idee (am Besten mit Pseudocode o.A. damit ich mich an irgendetwas festhalten kann).
    Vielen Dank


  • Mod

    Das kann man so machen und es wird funktionieren und es ist (bis auf die Paketgröße) auch die übliche Methode.



  • Verhält es sich tatsächlich so, das die Daten in 64k Blöcken verschickt wird?



  • Auf den unteren Ebenen des Schichtenmodells schon, doch sind nicht alle Bytes deine Daten, da ist noch einiges an Verwaltungskram dabei.
    Doch so mit um die 30-40 bytes deiner eigenen Daen kannst du schon rechnen.

    Das hängt halt damit zusammen dass sichergestellt werden muss, dass ein Sender lange genug schreibt bis die Daten in der Theorie die größte Strecke in einem Segment zwei mal zurücklegen können, halt hin und zurück und zwar noch bevor der Sender mit schreiben fertig ist.

    Falls dich sowas interessiert mal ein Paar Begriffe zum nachschlagen:
    Jam Signal, CSMA/CD, Ethernet, Ethernetframe, payload, Netwerk segment
    ISO OSI Schichtenmodell

    So genau kenne ich mich da jedoch auch nicht aus.
    Zum einen gilt das so wie hier nur in klassichen Ethernet umgebungen (worum es sich bei so gut wie jedem "normalen" Heimnetzwerk wohl noch handeln dürfte) und zum anderen ist es ziemlihc lange her alsich mich zuletzt damit beschäftigt habe, weswegen das eventuell auch schon veraltet sein kann, ka.
    Bin halt kein Techniker.

    EDIT:
    Aber das sind jetzt keine Werte mit denen man ohne tiefere Ahnung wirklich rumrechnen kann.
    Diese Ethernetframes sind was anderes als TCP Pakete und sobald du diese komischen Dinger ins Internet loslässt wo ja die Sendetechnik geändert ist, wird der ganze Kram nochmal in ganz anderen Kram umgewandelt.



  • Ah okay. Vielen Dank für die Informationen.
    Ich schaus mir gleich mal an.



  • Also. Ich habe jetzt eine Methode gefunden, eine Datei zu kopieren. Dafür benutze ich folgenden Code:

    ifstream DateiLesen ("C:\\read.exe", ios::binary);
    ofstream DateiSpeichern ("C:\\save.exe", ios::trunc | ios::binary);
    DateiSpeichern << DateiLesen.rdbuf ();
    DateiSpeichern.close ();
    DateiLesen.close ();
    

    Das ganze klappt auch, jedoch weiß ich nicht, wie ich das auf mein Client Server Modell übertragen kann.


  • Mod

    Du musst die Datei schon in irgendeine Datenstruktur einlesen, die du dann in Pakete packst und verschickst. Ein char Array bietet sich für so etwas an.

    Pseudocode Server:

    Datei öffen;
    Schicke ein Signal an Client, dass es losgeht;
    So lange noch nicht Dateiende erreicht
     {
       Lese ein Stückchen der Datei in char Array;
       Verschicke char Array;
     }
    Schicke ein Signal an Client, dass fertig;
    

    Pseudocode Client:

    Wenn Signal zum loslegen empfangen{
     So lange bis Endsignal empfangen
      {
        Empfange Paket;
        Hänge Paketinhalt an Datei an;
      }
    


  • Ja, das klingt sinnvoll, jedoch war ich mir nicht sicher ob dies funktioniert.
    Kannst du mir sagen, wie ich ein einzelnes Zeichen (oder Zeichenblöcke) aus einer Datei kopieren kann?


  • Mod

    DerCoder schrieb:

    Kannst du mir sagen, wie ich ein einzelnes Zeichen (oder Zeichenblöcke) aus einer Datei kopieren kann?

    Entweder ist die Antwort trivial oder ich verstehe nicht, was du meinst. Weißt du etwa nicht wie man aus Dateien liest?



  • Doch doch, das weiß ich schon 😛 Nur frage ich mich ob es schnell genug ist, wenn ich eine Zeile aus der Datei auslese und sie komplett versende oder immer nur substrings...

    *edit*
    Okay es klappt 🙂 Ich war mir nicht sicher. Vielen Dank für deine Hilfe.

    *edit2*
    Lol, doch nicht.
    Ich benutze folgenden Code um die Datei Blockweise zu verschicken:

    ifstream fileIn("C:\\programmIn.exe", ios::binary);
        while (!fileIn.eof ())
        {
            string stringFileBuffer ("");
            char buffer[64];
            fileIn.read (buffer, sizeof(buffer));
            stringFileBuffer = buffer;
            MyMessObj.SendMessagePort (stringFileBuffer);
        }
    	fileIn.close ();
    

    und zum empfangen:

    // im header bereich:
    ofstream fileOut ("C:\\programmOut.exe", ios::trunc | ios::binary);
    // im rec thread:
        char temp[4096];
    	int iStat;
    
    	iStat = recv (sRecSocket, temp, sizeof (temp), 0);
    	if (iStat == -1)
    	{
    		m_vClientList.remove (sRecSocket);
    		return 1;
    	}
    	else
    	{
               string InputMessage (temp);
               fileOut.write (InputMessage.c_str (), sizeof(InputMessage.c_str ()));
               fileOut.flush ();
            }
    // programm ende:
    fileOut.close ();
    

    Die erstellte Datei ist allerdings nur 1KB groß.



  • Der Fehler liegt bei dir in der Umwandlung von char* nach string: der Konstruktor string(char 😉 erwartet einen null-terminierten C-String!!!

    Und der zweite Fehler: der Rückgabewert von 'recv' gibt die Anzahl der gelesenen Bytes an, d.h. kopiere die Daten direkt:

    int count = recv(...);
    if(count >= 0)
    {
      fileOut.write (temp, count);
    }
    

    Edit: Tippfehler...

    P.S. habe gerade noch deinen 3. Fehler entdeckt: sizeof(InputMessage.c_str ())
    Überleg mal, welcher (konstante) Wert da raus kommt...



  • Arg. Ist mir nichtmal aufgefallen.
    Die Datei kommt allerdings immernoch nicht komplett an:

    iStat = recv (sRecSocket, temp, 4096, 0);
    	if (iStat >= 0)
    	{
            fileOut.write (temp, iStat);
            fileOut.flush ();
            }
    


  • Du hast beim Senden den selben Fehler drin (char * -> string)!!!



  • Hilft auch nicht wirklich ...

    *edit*
    Ich hab jetzt anstatt

    fileOut.write (temp, iStat);
    
    fileOut.write (temp, 64);
    

    ausprobiert. Die Datei kommt jetzt sogar noch größer an, als die Quelledatei ist.


Anmelden zum Antworten