IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

Transfert fichier par socket


Sujet :

Réseau C

  1. #1
    Membre du Club
    Profil pro
    Developpeur
    Inscrit en
    Septembre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Septembre 2004
    Messages : 114
    Points : 43
    Points
    43
    Par défaut Transfert fichier par socket
    Bonjour,

    Je suis actuellement en train de coder une petite application multi client qui consiste à transférer des fichiers du serveur au clien et inversement par socket (mode TCP).

    On essaye de transférer un fichier à l'aide de structure.
    Les affichage serveur montrent que tous les paquets sont bien envoyés mais à la réception, je recois des paquets qui ne correspondent pas à ceux envoyés.

    Cependant si je mets une instruction invalide après la réception du paquet dans le code client, le transfert s'execute correctement

    Voici le code incriminé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // On ouvre le fichier en ecriture
    			fichier = fopen(filePath,"w+b");
    			if(fichier!=NULL){ 				 
    				// On reconstruit le fichier
    				 while (tailleFichier<entete.size){
    					lon = recv(sd, &cmd, sizeof(command), 0);
    					fwrite(cmd.result,cmd.size,1,fichier);
    					tailleFichier = tailleFichier+cmd.size;
    					printf("Paquet n°%d de %d bits\n",cmd.num,lon);
    					printf("NB Ecrits : %d octets\n",cmd.size);
    					printf("Avancement : %d/%d \n",tailleFichier,entete.size);
    					printf("Type : %s \n Arg :%s\n",cmd.type,cmd.arg);
    					system("pause()");
    				}
    				fclose(fichier);
    				printf("Fichier crée avec une taille de %d octets\n",tailleFichier);
    			}
    Le code serveur pour l'envoi :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    while(!feof(fichier)){
    					nb_bloc_lus = fread(&cmd.result,BLOC,1,fichier);				
    					if(nb_bloc_lus==0) cmd.size = (taille-m);
    					else cmd.size = BLOC;
    					cmd.num=numPaquet;
    					printf("Paquet n°%d\n",cmd.num);
    					printf("NB Lus : %d octets (%d)\n",cmd.size,(taille-m));				
    					send(soc,&cmd, sizeof(command),0);
    					m=m+cmd.size;	
    					printf("Avancement : %d/%d \n",m,taille);			
    					numPaquet++;				
    				}
    La structure adaptée pour la commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    typedef struct{
     char type[10];
     char arg[50];
     char result[BLOC];
     unsigned long  size;
     unsigned long  num;
    }command;
    Merci d'avance à tout ceux qui pourront m'aider

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par allserv Voir le message
    Je suis actuellement en train de coder une petite application multi client qui consiste à transférer des fichiers du serveur au clien et inversement par socket (mode TCP).

    On essaye de transférer un fichier à l'aide de structure.
    Une structure, c'est bien en interne, mais sur le réseau ce n'est pas du tout portable. Le plus simple est de sérialiser en mode texte.

    http://emmanuel-delahaye.developpez....m#enreg_struct

    "w+b" c'est pas bon. C'est "wb".

    feof() ne fait pas ce que tu crois. Il faut tester la valeur retournée par la fonction de lecture.

    http://emmanuel-delahaye.developpez....s.htm#fichiers

    Le format "%d" attend un int et non un unsigned long... Il faut "%lu".

    J'ai testé la chose comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
     
    #include <stdio.h>
    #include <stdlib.h>
     
    #define BLOC 8
     
    typedef struct
    {
       char type[10];
       char arg[50];
       char result[BLOC];
       unsigned long size;
       unsigned long num;
    }
    command;
     
    /* network simulator */
    typedef int SOCKET;
     
    static FILE *G_net;
     
    static int recv (SOCKET fd, void *data, int size, int a)
    {
       int n = -1;
       if (G_net != NULL)
       {
          n = fread (data, size, 1, G_net);
       }
     
       (void) fd;
       (void) a;
       return n;
    }
     
    static int send (SOCKET fd, void const *data, int size, int a)
    {
       int n = -1;
       if (G_net != NULL)
       {
          n = fwrite (data, size, 1, G_net);
       }
     
       (void) fd;
       (void) a;
       return n;
    }
     
    static void recevoir (SOCKET sd, char const *filePath)
    {
    /* On ouvre le fichier en ecriture */
       FILE *fichier = fopen (filePath, "wb");
       if (fichier != NULL)
       {
          command entete  = { "", "", "", 0, 0 };;
     
          recv (sd, &entete, sizeof (command), 0);
     
          unsigned long tailleFichier = 0;
     
          /* On reconstruit le fichier */
          while (tailleFichier < entete.size)
          {
          command cmd=  { "", "", "", 0, 0 };
         int lon = recv (sd, &cmd, sizeof (command), 0);
             fwrite (cmd.result, cmd.size, 1, fichier);
             tailleFichier = tailleFichier + cmd.size;
             printf ("Paquet n°%lu de %d bits\n", cmd.num, lon);
             printf ("NB Ecrits : %lu octets\n", cmd.size);
             printf ("Avancement : %lu/%lu \n", tailleFichier, entete.size);
             printf ("Type : %s \n Arg :%s\n", cmd.type, cmd.arg);
             system ("pause()");
          }
          fclose (fichier);
          printf ("Fichier crée avec une taille de %lu octets\n", tailleFichier);
       }
    }
     
    static unsigned long get_size (char const *fname)
    {
       unsigned long size = 0;
       FILE *fp = fopen (fname, "rb");
       if (fp != NULL)
       {
          fseek (fp, 0, SEEK_END);
          size = ftell (fp);
          fclose (fp), fp = NULL;
     
          printf ("size = %lu\n", size);
       }
       return size;
    }
     
    static void envoyer (SOCKET sd, char const *fname)
    {
       unsigned long taille = get_size (fname);
       if (taille != 0)
       {
          FILE *fichier = fopen (fname, "rb");
          if (fichier != NULL)
          {
             int end = 0;
             command cmd = { "", "", "", 0, 0 };
     
             unsigned long m = 0;
             unsigned long numPaquet = 0;
     
    /* en-tete */
             cmd.size = taille;
             send (sd, &cmd, sizeof (command), 0);
     
             while (!end)
             {
                int nb_bloc_lus = fread (&cmd.result, BLOC, 1, fichier);
                if (nb_bloc_lus == 0)
                {
                   cmd.size = (taille - m);
                   end = 1;
                }
                else
                {
                   cmd.size = BLOC;
                }
                cmd.num = numPaquet;
                printf ("Paquet n°%lu\n", cmd.num);
                printf ("NB Lus : %lu octets (%lu)\n", cmd.size, (taille - m));
                send (sd, &cmd, sizeof (command), 0);
                m = m + cmd.size;
                printf ("Avancement : %lu/%lu \n", m, taille);
                numPaquet++;
             }
             fclose (fichier), fichier = NULL;
          }
          else
          {
             perror(fname);
          }
       }
    }
     
    int main (void)
    {
       if (G_net == NULL)
       {
          G_net = fopen ("net.bin", "wb");
          if (G_net != NULL)
          {
             printf("envoyer()\n");
             envoyer (0, "out.txt");
    #if 1
             G_net = freopen ("net.bin", "rb", G_net);
          }
     
          if (G_net != NULL)
          {
             printf("recevoir()\n");
             recevoir (0, "in.txt");
          }
     
          if (G_net != NULL)
          {
    #endif
     
             fclose (G_net), G_net = NULL;
          }
       }
       return 0;
     
    }
    Cette méthode de transfert de données n'est pas du tout optimisée. Pour un simple :
    On a ceci sur le réseau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    00000000h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000040h: 00 00 00 00 0C 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    00000080h: 00 00 00 00 00 00 00 00 48 65 6C 6C 6F 20 77 6F ; ........Hello wo
    00000090h: 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    000000a0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    000000b0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    000000c0h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
    000000d0h: 00 00 00 00 72 6C 64 0A 6F 20 77 6F 04 00 00 00 ; ....rld.o wo....
    000000e0h: 01 00 00 00                                     ; ....
    Le méthodes habituelles consistent à
    - mesurer la taille du fichier
    - passer en mode texte :
    -- La taille
    -- Le nom du fichier
    -- Les droits éventuels
    -- Toute information intéressante

    Ensuite, on fait un transfert binaire du fichier par bloc. On laisse TCP/IP encapsuler les données... Pas besoin de structures supplémentaires...

    En réception, on stocke ce qui est reçu à l'endroit indiqué et on fait les comptes. Quand le compte est bon, on ferme le fichier.

    Un timeout (select()) peut éventuellement gérer un problème de réception incomplète ou de transmission HS.

Discussions similaires

  1. Transfert de fichier par socket client vers client
    Par Dasson dans le forum Entrée/Sortie
    Réponses: 21
    Dernier message: 17/04/2012, 02h26
  2. Transfert de fichiers par socket
    Par hebus44 dans le forum Entrée/Sortie
    Réponses: 6
    Dernier message: 27/10/2007, 13h55
  3. Transfert fichier par FTP
    Par j_bolduc dans le forum VB 6 et antérieur
    Réponses: 3
    Dernier message: 23/11/2005, 19h59
  4. Transfert de fichiers par sockets
    Par Kaori dans le forum C++
    Réponses: 19
    Dernier message: 26/01/2005, 13h58
  5. [Débutant] Envoi de fichier par socket
    Par zapho dans le forum Entrée/Sortie
    Réponses: 13
    Dernier message: 26/05/2004, 18h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo