Datei senden



  • Servus an alle C Programmierer,

    ich habe ein Programm geschrieben, mit dem man Dateien versenden kann. Das Problem ist, dass größere(binäre) Dateien nur ankommen, wenn ich sie mir selber schicke(127.0.0.1). Daraus ziehe ich den Schluss, dass es am Versenden der Daten liegt:

    f=fopen(Datei,"rb");
    
    while(fread(data,sizeof(short),1,f)!=0)
    {
            sleep(1);
            Verbindung=send(Socket,data,100,0); 
            if (Verbindung == SOCKET_ERROR) 
            {              
                            printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                            system("Pause");
                            closesocket(Socket);
                            WSACleanup();
                            return 0;
            }
    }
    fclose(f);
    

    Wie kann ich diesen Code so verbessern, dass alles richtig ankommt?

    Ich freu mich auf jede Hilfe,

    Felix



  • Dein Codeausschnitt ist ein bisschen wenig. Was für ein Protokoll verwendest du z.B.?



  • Die Clientanwendung:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    int main(int argc, char *argv[])
    {
    int Socket;
    int Laenge;
    int Verbindung;
    struct sockaddr_in Adressinfo;
    
    char Nachricht[1024];
    char Antwort[1024];
    char Text[1024];
    char Datei[1024];
    char Neuer_Name[1024];
    
    //char *data;
    char data[100];
    
    char bit[1024];
    
    FILE *f;
    
    char buffer[100];
    long file_size;
    int bytes_sent, byte_recieved;
    
    int Port = 12345;
    char Ip_Adresse[1024];//Ip des c-programmieren.com Servers
    
    int o;
    
    printf("Geben sie die Ip des Betreffenden an: ");
    scanf("%s",&Ip_Adresse); 
    getchar();
    
    printf("Geben sie die Datei ein, die sie verschicken wollen: ");
    scanf("%s",&Datei); 
    getchar();
    
    printf("Wie soll sie nach dem verschicken heissen: ");
    scanf("%s",&Neuer_Name); 
    getchar();
    
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0)
    {
    printf("WSA konnte nicht initialisiert werden.\n\n");
    system("PAUSE");
    return 0;
    }
    
    Socket = socket(AF_INET, SOCK_STREAM, 0);
    Adressinfo.sin_family = AF_INET;
    Adressinfo.sin_addr.s_addr = inet_addr(Ip_Adresse);
    Adressinfo.sin_port = htons(Port);
    Laenge = sizeof(Adressinfo);
    
    Verbindung = connect(Socket, (struct sockaddr *)&Adressinfo, Laenge);
    if (Verbindung == 0)
    {
                   printf("Verbindungsaufbau erfolgreich!");
    }
    else
    {
                   printf("Verbindungsaufbau ist fehlgeschlagen!");
    }
    printf("\n\n");
    
    sleep(1);
    Verbindung=send(Socket,Neuer_Name,strlen(Neuer_Name),0); 
    if (Verbindung == SOCKET_ERROR) 
    {              
                    printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                    system("Pause");
                    closesocket(Socket);
                    WSACleanup();
                    return 0;
    }
    else
    {
                    printf("Der Name der Datei wurde verschickt!\n",Nachricht);
    }
    
    f=fopen(Datei,"rb");
    
    fseek(f, 0, SEEK_END);
    file_size = ftell(f);
    itoa(file_size, buffer, 10);
    
    send(Socket, buffer, (int)strlen(buffer), 0);
    
    fclose(f);
    
    f=fopen(Datei,"rb");
    
    while(fread(data,sizeof(short),1,f)!=0)
    {
            sleep(1);
            Verbindung=send(Socket,data,100,0); 
            if (Verbindung == SOCKET_ERROR) 
            {              
                            printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                            system("Pause");
                            closesocket(Socket);
                            WSACleanup();
                            return 0;
            }
    }
    fclose(f);
    
    sleep(1000);
    
    Verbindung=send(Socket,"Ende",strlen("Ende"),0); 
    if (Verbindung == SOCKET_ERROR) 
    {              
                    printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                    system("Pause");
                    closesocket(Socket);
                    WSACleanup();
                    return 0;
    }
    else
    {
                    printf("Die Datei wurde verschickt!\n",Nachricht);
    }
    
    sleep(1000);
    
    closesocket(Socket); 
    
    WSACleanup();
    
    system("PAUSE");
    return 0;
    }
    


  • Und wie empfängst du die Daten (Server-Programm). Kommen dort denn Teile der Datei an?

    OK, habe gerade gesehen, daß du einen Fehler in deiner Sende-Routine hast.
    Du liest immer nur 2 Byte (short ???), sendest aber immer 100 Bytes...



  • char Ip_Adresse[1024];//Ip des c-programmieren.com Servers
    

    das sind 1020 verschwendete bytes.
    🙂



  • Ich hab die Programme jetzt noch ein bisschen verändert:

    Client-Anwendung:

    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    
    int main(int argc, char *argv[])
    {
    int Socket;
    int Laenge;
    int Verbindung;
    struct sockaddr_in Adressinfo;
    
    char Nachricht[1024];
    char Antwort[1024];
    char Text[1024];
    char Datei[1024];
    char Neuer_Name[1024];
    
    char data[100];
    
    char bit[1024];
    
    FILE *f;
    
    char buffer[100];
    long file_size;
    
    int Port = 12345;
    char Ip_Adresse[100];//Ip des c-programmieren.com Servers
    
    int o;
    
    printf("Geben sie die Ip des Betreffenden an: ");
    scanf("%s",&Ip_Adresse); 
    getchar();
    
    printf("Geben sie die Datei ein, die sie verschicken wollen: ");
    scanf("%s",&Datei); 
    getchar();
    
    printf("Wie soll sie nach dem verschicken heissen: ");
    scanf("%s",&Neuer_Name); 
    getchar();
    
    WSADATA wsaData;
    if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0)
    {
    printf("WSA konnte nicht initialisiert werden.\n\n");
    system("PAUSE");
    return 0;
    }
    
    Socket = socket(AF_INET, SOCK_STREAM, 0);
    Adressinfo.sin_family = AF_INET;
    Adressinfo.sin_addr.s_addr = inet_addr(Ip_Adresse);
    Adressinfo.sin_port = htons(Port);
    Laenge = sizeof(Adressinfo);
    
    Verbindung = connect(Socket, (struct sockaddr *)&Adressinfo, Laenge);
    if (Verbindung == 0)
    {
                   printf("Verbindungsaufbau erfolgreich!");
    }
    else
    {
                   printf("Verbindungsaufbau ist fehlgeschlagen!");
    }
    printf("\n\n");
    
    sleep(1);
    Verbindung=send(Socket,Neuer_Name,strlen(Neuer_Name),0); 
    if (Verbindung == SOCKET_ERROR) 
    {              
                    printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                    system("Pause");
                    closesocket(Socket);
                    WSACleanup();
                    return 0;
    }
    else
    {
                    printf("Der Name der Datei wurde verschickt!\n",Nachricht);
    }
    
    f=fopen(Datei,"rb");
    
    fseek(f, 0, SEEK_END);
    file_size = ftell(f);
    itoa(file_size, buffer, 10);
    
    send(Socket, buffer, (int)strlen(buffer), 0);
    
    fclose(f);
    
    f=fopen(Datei,"rb");
    
    while(fread(data,sizeof(short),1,f)!=0)
    {
            sleep(1);
            Verbindung=send(Socket,data,2,0); 
            if (Verbindung == SOCKET_ERROR) 
            {              
                            printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                            system("Pause");
                            closesocket(Socket);
                            WSACleanup();
                            return 0;
            }
    }
    fclose(f);
    
    sleep(1000);
    
    Verbindung=send(Socket,"zz",strlen("zz"),0); 
    if (Verbindung == SOCKET_ERROR) 
    {              
                    printf("Die Nachricht konnte nicht verschickt werden: %d\r\n", WSAGetLastError());
                    system("Pause");
                    closesocket(Socket);
                    WSACleanup();
                    return 0;
    }
    else
    {
                    printf("Die Datei wurde verschickt!\n",Nachricht);
    }
    
    sleep(1000);
    
    closesocket(Socket); 
    
    WSACleanup();
    
    system("PAUSE");
    return 0;
    }
    

    Server-Anwendung:

    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    
    int startWinsock(void)
    {
      WSADATA wsa;
      return WSAStartup(MAKEWORD(2,0),&wsa);
    }
    
    int main()
    {
        long rc;
        SOCKET acceptSocket;
        SOCKET connectedSocket;
        SOCKADDR_IN addr;
        int Verbindung=1;
    
        char buffer[100];
        long file_size;
        int bytes_recieved;
    
        char Datei[1024];
        char Data[10];
    
        FILE *f;
    
        rc=startWinsock();
    
        if(rc!=0)
        {
             printf("Fehler: startWinsock, fehler code: %d\n",rc);
             system("Pause");
             return 0;
        }
        else
        {
              printf("Winsock gestartet!\n");
              acceptSocket=socket(AF_INET,SOCK_STREAM,0);
    
              if(acceptSocket==INVALID_SOCKET)
              {
                            printf("Fehler: Der Socket konnte nicht erstellt werden, fehler code: %d\n",WSAGetLastError());
                            system("Pause");
                            return 0;
              }
              else
              {
                            printf("Socket erstellt!\n");
              }
    
              memset(&addr,0,sizeof(SOCKADDR_IN));
              addr.sin_family=AF_INET;
              addr.sin_port=htons(12345);
              addr.sin_addr.s_addr=ADDR_ANY;
    
              rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN));
              if(rc==SOCKET_ERROR)
              {
                         printf("Fehler: bind, fehler code: %d\n",WSAGetLastError());
                         system("Pause");
                         return 0;
              }
              else
              {
                         printf("Socket an port 12345 gebunden\n");
              }
    
              rc=listen(acceptSocket,10);
              if(rc==SOCKET_ERROR)
              {
                       printf("Fehler: listen, fehler code: %d\n",WSAGetLastError());
                       system("Pause");
                       return 0;
              }
              else
              {
                       printf("acceptSocket ist im listen Modus....\n"); 
              }
    
              connectedSocket=accept(acceptSocket,NULL,NULL);
              if(connectedSocket==INVALID_SOCKET)
              {
                      printf("Fehler: accept, fehler code: %d\n",WSAGetLastError());
                      system("Pause");
                      return 0;
              }
              else
              {
                      printf("Neue Verbindung wurde akzeptiert!\n");
              }
    
              Verbindung=recv(connectedSocket,Datei,1023,0); 
              if(Verbindung==0) 
              { 
                        printf("Server hat die Verbindung getrennt..\n");
              } 
              if(Verbindung==SOCKET_ERROR) 
              { 
                        printf("Fehler bei Empfangen: %d\n",WSAGetLastError());
              } 
              Datei[Verbindung]='\0'; 
              printf("\nDatei:%s\n",Datei);
    
              bytes_recieved = recv(connectedSocket, buffer, 100, 0);
              buffer[bytes_recieved] = '\0';
              file_size = atoi(buffer);
    
              printf("Dateigroesse: %d\n\n\n",file_size);
    
              f=fopen(Datei,"w+b");
    
              while(Verbindung!=SOCKET_ERROR) 
              { 
                       Verbindung=recv(connectedSocket,Data,2,0); 
                       Data[Verbindung]='\0';
                       if(Verbindung==0) 
                       { 
                                         printf("Server hat die Verbindung getrennt..\n"); 
                                         break; 
                       } 
                       if(Verbindung==SOCKET_ERROR) 
                       { 
                                         printf("Fehler bei Empfangen: %d\n",WSAGetLastError()); 
                                         break; 
                       }
    
                       if(strstr(Data,"zz")!=NULL)
                       {
                                         printf("Die Datei wurde empfangen.\n\n");
                                         break;           
                       }
                       else
                       {
                                         fwrite(Data,sizeof(short),1,f);
                       }
              } 
              fclose(f);
    
              closesocket(connectedSocket);
              closesocket(acceptSocket);
    
              system("Pause");
    
              return 0;
       }
    }
    

    Ich hab die Anzahl der Byte, die verschickt werden auf 2 Byte beschränkt, wie TH vorgeschlagen hat und das char Array ein bisschen gekürzt. Ich befürchte nur, dass mich das nicht besonders weiter bringt.





  • Ich habe dir nicht gesagt, du sollst immer nur 2 Byte lesen und schreiben, sondern dir nur deinen Fehler genannt.

    Du sollst soviele Daten senden, wie du gelesen hast:

    int anzahl;
    while(anzahl = fread(data,sizeof(char),100,f), anzahl!=0) // char statt short
    {
            // sleep(1); // unnütz
            Verbindung=send(Socket, data, anzahl,0);
            if (Verbindung == SOCKET_ERROR)
              ...
    }
    

    Außerdem hast du vorher noch einen ähnlichen Fehler beim Übertragen des Dateinamens (laß den erst mal auf beiden Seiten weg).

    Und du solltest die einzelnen Aktionen in Funktionen packen, dann wäre dein Code ein wenig lesbarer...

    Da du die Grundlagen des Senden und Empfangen von Daten (insbesonder Strings) noch nicht richtig verstanden hast, solltest du erst mal einen Wert übertragen und dann nach und nach mehr Werte übertragen.



  • char Ip_Adresse[100];//Ip des c-programmieren.com Servers
    

    das sind jetzt 96 verschwendete bytes.
    🙂



  • Bouncer, du bist einfach nur krank.

    Felix15: ignoriere die Spam-Einträge von ihm einfach.

    Es ist schon richtig, daß du für den Namen bzw. die Adresse eines TCP/IP-Servers ein char-Array mit ausreichender Länge benutzt.

    "127.0.0.1", "localhost" oder "MySuperServer" passen einfach nicht in 4 Bytes...



  • Th schrieb:

    "127.0.0.1", "localhost" oder "MySuperServer" passen einfach nicht in 4 Bytes...

    na, wenn da text rein soll, dann hat die variable aber einen falschen namen.
    🙂



  • Das hilft mir jetzt aber auch nicht viel weiter!



  • Felix: wo hast du denn jetzt noch konkrete Probleme?



  • Felix15 schrieb:

    Das hilft mir jetzt aber auch nicht viel weiter!

    hast du den link von ,,,,,,,,, beachtet?
    ansonsten, hier mal zwei funktionen, die demonstrieren wie man alles restlos empfangen und senden kann. sind zwar für non-blocking sockets, aber das prinzip gilt ja auch so (das weiterzählen des pointers, etc.)

    static int RC_send_all (SOCKET sock, char *buff, int size)
    {
        while (size)
        {
            int res = send (sock, buff, size, 0);
            if (res == SOCKET_ERROR)
            {
                if (WSAGetLastError() == WSAEWOULDBLOCK)
                {
                    // socket buffer full, let winsock suck it away
                    Sleep (1000);   
                    continue;
                }
                // serious error or disconnected
                return -1;
            }
            size -= res;
            buff += res;
        }
    
        return 0;
    }
    
    static int RC_recv_all (SOCKET sock, char *buff, int size)
    {
        DWORD timeout = GetTickCount() + 5000;
    
        while (size)
        {
            int res = recv (sock, buff, size, 0);
            // Connection closed? --> exit
            if (res == 0)
                goto fail;
            // recv failed?
            else if (res == SOCKET_ERROR)
            {
                // No data?
                if (WSAGetLastError() == WSAEWOULDBLOCK)
                {
                    // Timed out --> exit
                    if (timeout < GetTickCount())
                        goto fail;
                    // Retry
                    Sleep(10);
                    continue;
                }
                // Any other error (that is a real one) --> exit
                goto fail;
            }
            // Rx next chunk
            size -= res;
            buff += res;
        }
    
        // All Rx'd
        return 0;
    
        fail:
        return -1;
    }
    


  • Am Anfang der gesendeten Datei tritt ein Fehler auf:

    Orginaldatei:

    MZ       ÿÿ  ¸       @                                   €   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
    
    $       PE  L –ä¼D   å  à 8 
                        @                     `     Ýë                                  P  Ø
    

    empfangene Datei:

    @                                   €   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
    
    $       PE  L –ä¼D   å  à 8 
                        @                     `     Ýë                                  P  Ø
    

    Irgendwie fehlen die ersten paar Bytes:

    MZ       ÿÿ  ¸
    

    Warum?



  • Ich hab's geschafft. Es war ein sleep zu wenig. Nach dem Senden der Größe muss beim Clienten ein sleep rein, dann empfängt der Server alles.

    Danke für eure Hilfe,

    Felix



  • Überträgst du denn vorher immer noch den Dateinnamen und kommt dieser richtig an, d.h. auch hier müßtest du vorher die Größe als int zuerst übertragen (oder aber immer ein konstantes Array - NICHT strlen(name)!!!)???

    Edit: das mit dem Sleep() kann nicht die richtige Lösung sein (auch wenn es jetzt mal funktioniert, aber darauf kannst du dich bei Netzwerkübertragungen nicht verlassen)...

    Du mußt schon auf Client und Server jeweils die exakt gleichen Daten senden und empfangen (und das machst du anscheined nicht, sonst würde es auch ohne Wartezeit funktionieren).



  • Th schrieb:

    Du mußt schon auf Client und Server jeweils die exakt gleichen Daten senden und empfangen (und das machst du anscheined nicht, sonst würde es auch ohne Wartezeit funktionieren).

    Dazu hätte ich eine Frage. Ich suche schon seit Ewigkeiten eine halbwegs vernünftige (und auch sichere) Version Dateien übers netzwerk zu versenden (Internet mit eingeschlossen.) Wie würde denn ein Beispiel aussehen wo man die Daten exakt empfängt oder gesendet bekommt? (Ohne Wartezeit Sleep)

    Die Dateien müssen 100% ankommen, deswegen wäre ich an einer Version ohne die Wartezeit gerne interessiert, ich suche schon ne ganze Weile nach einem Tutorial welches das ganze mal übersichtlich aufzeigt. Aber finde irgendwie nix anständiges... 😡

    Komme irgendwie nicht weiter, und nochmal so ne blöde Frage am Schluss:

    Muss man irgendwas beachten um binäre Dateien zu verschicken? Bei TextDateien und so... hat es halbwegs vernünftig geklappt aber bei binären Dateien sah ich alt aus... 😑

    P.s. Die Dateien werden richtig eingelesen und auch über buffer verschickt, darauf habe ich geachtet.

    Wäre für Hilfe sehr dankbar, wie gesagt dieses Thema macht mich noch verrückt. 😃



  • Nicht, dass es hier falsch verstanden wird bzgl. der Sleep()-Funktion.
    Ich meine, man braucht kein Sleep() in der normalen Sende- bzw. Einleseschleife. Dagegen kann ein Sleep() bei einem möglichen SOCKET_ERROR Sinn machen (Timeout, Connection lost, etc.), aber dann sollte man eher versuchen die Verbindung noch mal neu auzubauen.

    Bei binären Daten muß man nur wissen, daß es eben kein Endekennzeichen gibt (da alle 256 char-Werte Daten sind). Somit überträgt man am besten im Voraus die Anzahl (z.B. als unsigned long), damit der Empfänger einen entsprechenden Hinweis auf die Datenlänge hat (um einen Puffer zu allokieren und nur genau so viele Daten anzufordern, wie angegeben wurden).


Anmelden zum Antworten