Datei über Socket senden



  • Hi Leute,

    hab ein kleines Problem. Versuche ne Datei über einen Socket zu senden.
    Jedoch verschickt er nicht Alles, sondern nur einen Teil der Datei.

    Recive

    void
    recive () {
    
    	char swrite[1024];
    	FILE *fwrite;
    	int i;
    
    	fwrite = fopen("file","a+");
    	i = recv(sock,swrite,sizeof(swrite),0);
    
    	for (;;) {
    		if (i == -1 || strcmp (swrite, "_exit_")== 0)
    			break;
    		fprintf(fwrite,"%s",swrite);
    	}
    
    	fclose(fwrite);
    }
    

    send

    void
    send (a) {
    
        static char buffer[1025];
        FILE *file;
        int i;
    
        file = fopen("somefile","r");
        i = send(socket,buffer,sizeof(buffer),0);
    
        while (fgets(buffer,1024,file)) { 
            if (i == -1)
                break;
            memset(&buffer[0], 0, sizeof(buffer));
        }
        send(socket,"_exit_",7,0);
    }
    

    Und da wäre noch eine Frage - der Socket verschickt die Daten viel zu schnell hinter einander, so das der Empfänger nicht hinterher kommt. Soll er daher immer mit dem Verschicken warten bis er ne Antwort bekommen hat? Oder habt ihr ne andere Idee.



  • Ich würde ja versuchen, die Daten erst einzulesen, bevor ich sie auch sende 😉 (sprich: der send()-Aufruf sollte innerhalb der while-Schleife stehen)

    Außerdem prüfst du nicht, wieviel du wirklich gelesen hast. Und bei der Abbruchbedingung für's Empfangen bin ich auch nicht so sicher, ob das funktioniert.



  • Crap, falsch abgeschriben. Er verschickt die Datei auch, weiß auch wo das Ende ist .. Zumindest bei einfachen Textdateien. Wenn ich ein Bild verschick , dann wird jedoch nur ein Teil versendet.

    void
    recive () {
    
    	char swrite[1024];
    	FILE *fwrite;
    	int i;
    
    	fwrite = fopen("file","a+");
    
    	for (;;) {
    		i = recv(sock,swrite,sizeof(swrite),0);
    		if (i == -1 || strcmp (swrite, "_exit_")== 0)
    			break;
    		fprintf(fwrite,"%s",swrite);
    	}
    
    	fclose(fwrite);
    }
    

    send

    void
    send (a) {
    
        static char buffer[1025];
        FILE *file;
        int i;
    
        file = fopen("somefile","r");
    
        while (fgets(buffer,1024,file)) {
        i = send(socket,buffer,sizeof(buffer),0); 
            if (i == -1)
                break;
            memset(&buffer[0], 0, sizeof(buffer));
        }
        send(socket,"_exit_",7,0);
    }
    


  • Wozu sind denn die (for bzw. while) Schleifen da?
    Wie sollen sich in der for-Schleife denn die Inhalte von i oder swrite ändern?

    send verschickt die Daten packetweise. Große Datensätze werden in kleinere aufgeteilt. Kleine Datensätze werden evtl. gesammelt.

    recv liest das ein, was im Empfangspuffer steht.



  • akoww schrieb:

    Crap, falsch abgeschriben.

    Nicht abschreiben, Copy & Paste 🙄

    Ich ziehe die beiden Fragen zurück.



  • akoww schrieb:

    Crap, falsch abgeschriben. Er verschickt die Datei auch, weiß auch wo das Ende ist .. Zumindest bei einfachen Textdateien. Wenn ich ein Bild verschick , dann wird jedoch nur ein Teil versendet.

    Ich vermute mal, daß doch das komplette Bild versendet wird - allerdings kommt fprintf() nicht besonders gut mit 0x00 in den zu schreibenden Daten zurecht -> versuch's mal mit fwrite().

    Ansonsten: Beim letzten Block der Datei sendest du definitiv zu viel - und ob die Ende-Marke wirklich alleine (oder überhaupt an einem Stück) empfangen wird, kann dir auch niemand garantieren.



  • fgets ist auch die falsche funktion um Binärdaten (wie Bilder) einzulesen.
    Versuch mal fread



  • @DirkB
    Es ist doch egal ob sich i ändert oder nicht. Es geht darum, dass der buffer sich ändert und auch der verschickt wird. Der buffer wird ja nach jedem verschicken aufs neue durch fgets gefüllt bis zum EOF.
    Und das mit swrite soll sich auch nichts ändern. Er soll einfach immer weiter in die Datei schreiben die ich angegeben habe.

    Das mit dem fgets und fprintf wusste ich nun nicht, das wird wohl mein Problem sein.

    Danke



  • Die Fragen nach i und swrite bezogen sich auf deine erste, falsche Version. Ich zog die Fragen bereits zurück.

    Das mit dem "_exit_" solltest du dir auch nochmal überlegen. Die Zeichenfolge kann auch in einem Bild vorkommen. Zudem muss sie nicht am Anfang des Buffers stehen.

    Du kannst am Anfang die Dateigröße senden oder die Verbindung beenden, wenn die Datei zu Ende ist.



  • akoww schrieb:

    Der buffer wird ja nach jedem verschicken aufs neue durch fgets gefüllt bis zum EOF.

    fgets mit fopen-"r" mappt gemäß Lineend-Convention. Deshalb ist deine Variante hinsichtlich Plattformunabhängigkeit zumindest fragwürdig und ein binäres Lesen wie vorgeschlagen weitaus besser geeignet.



  • Was soll das überhaupt für eine Funktion sein
    void
    send (a)
    oO

    So schwer ist das wirklich nicht:

    void SendFile(int sock, const char* filename)
    {
      char buf[0x1000];
      FILE *file = fopen(filename, "rb");
      while (!feof(file))
      {
        int rval = fread(buf, 1, sizeof(buf), file);
        send(sock, buf, rval, 0);
      }
      closesocket(sock);
    }
    
    void RecvFile(int sock, const char* filename)
    {
      int rval;
      char buf[0x1000];
      FILE *file = fopen(filename, "wb");
      while ((rval = recv(sock, buf, sizeof(buf), 0)) > 0)
      {
        fwrite(buf, 1, rval, file);
      }
      closesocket(sock);
    }
    

    (Ungetestet, jede Überpfüfung der Übersicht halber weggelassen.)

    Nachtrag:
    Es ist ohne ein darüber liegendes Protkoll nicht möglich, das Dateieende anders als durch einen Verbindungsabbruch zu markieren. Du kannst nicht wissen, was in einer Datei steht. Falls ein Verbindungsabbruch nicht in Frage kommt, definiere ein simples Protokoll. TCP gibt ja eh darauf acht, dass deine Pakete in der richtigen Reihenfolge empfangen werden, von daher ist das nicht soo schwer.


Anmelden zum Antworten