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 :

Envoi d'un fichier


Sujet :

Réseau C

  1. #1
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut Envoi d'un fichier
    Bonsoir,

    j'ai essayé de créer une application client/serveur permet d'envoyer un fichier en utilisant les socket en c.
    l’exécution du programme signale une erreur de type :
    Erreur de segmentation au moment de la réception des données:

    voici le code de la fonction qui reçoit le fichier :
    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
     
    int recvfile(int s,char* f){
     
    	int nbByte_lu, nbByte_ecrit ;
    	FILE * file ;
    	char buffer[MAX_SIZE];
     
    	file = fopen(f,"wb");
    	if(file==NULL){
    		printf("impossible de creer le fichier");
    		exit(-1);
    	}	
    	printf("\n fichier cree ...ok");
    	memset(buffer,0,sizeof(buffer));
    	while(1){
     
    		printf("\n reception en cours...sur le socket: %d",s);
    		nbByte_lu = recv(s,buffer,sizeof(char)*MAX_SIZE,0); // ==>Erreur apparait
    		if(nbByte_lu<0){
    			perror("reception !!!");
    			return -1;
    		}
     
    		if(nbByte_lu==0){
    			break;
    		}
     
    		printf("\n reception %d octet",nbByte_lu);
     
    		nbByte_ecrit = fwrite(buffer,sizeof(char),nbByte_lu,f);
     
    		if(nbByte_ecrit!=nbByte_lu)
    			return -1;
    	}
    	return 0;
    }
    le code de la fonction qui envoi le fichier
    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
     
    int recvfile(int s,char* f){
     
    	int nbByte_lu, nbByte_ecrit ;
    	FILE * file ;
    	char buffer[MAX_SIZE];
     
    	file = fopen(f,"wb");
    	if(file==NULL){
    		printf("impossible de creer le fichier");
    		exit(-1);
    	}	
    	printf("\n fichier cree ...ok");
    	memset(buffer,0,sizeof(buffer));
    	while(1){
     
    		printf("\n reception en cours...sur le socket: %d",s);
    		nbByte_lu = recv(s,buffer,sizeof(char)*MAX_SIZE,0);
    		if(nbByte_lu<0){
    			perror("reception !!!");
    			return -1;
    		}
     
    		if(nbByte_lu==0){
    			break;
    		}
     
    		printf("\n reception %d octet",nbByte_lu);
     
    		nbByte_ecrit = fwrite(buffer,sizeof(char),nbByte_lu,f);
     
    		if(nbByte_ecrit!=nbByte_lu)
    			return -1;
    	}
    	return 0;
    }
    Merci de m'aider
    E.Bazoga

  2. #2
    Responsable 2D/3D/Jeux


    Avatar de LittleWhite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2008
    Messages
    27 180
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2008
    Messages : 27 180
    Billets dans le blog
    156
    Par défaut
    Bonjour,

    Vous avez mis deux fois le code de réception.
    Lorsque vous avez une erreur de segmentation vous devez utiliser un débogueur pour comprendre où elle se situe et pourquoi elle se produit.
    Vous souhaitez participer à la rubrique 2D/3D/Jeux ? Contactez-moi

    Ma page sur DVP
    Mon Portfolio

    Qui connaît l'erreur, connaît la solution.

  3. #3
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    Merci pour votre réponse
    Citation Envoyé par LittleWhite Voir le message
    Bonjour,

    Vous avez mis deux fois le code de réception.
    ==> Effets de nuit
    Lorsque vous avez une erreur de segmentation vous devez utiliser un débogueur pour comprendre où elle se situe et pourquoi elle se produit.
    ==> l'erreur apparait des la première réception dans la fonction recvfile:

    voici le code d'envoi
    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
     
    int sendfile(int s, char* filename){
     
    	FILE* file;
    	int cumul,nbByte,env ;
    	long taille ;
    	char buffer[MAX_SIZE];
     
    	file = fopen(filename,"rb");
     
    	if(file==NULL){
    		printf("Impossible d'ouvrir le fichier");
    		exit(-1);
    	}
     
    	/*calculer la taille du fichier */
    	fseek(file,0,SEEK_END);
    	taille = ftell(file);
    	rewind(file);
     
    	/* l'envoi du fichier : suite de bloc de taille max 1024
    		le dernier bloc à recevoir est le bloc de taille <1024
    	*/
     
    	bzero(buffer,MAX_SIZE);
    	cumul=0;
     
    	do{
    		nbByte = fread(buffer,sizeof(char),MAX_SIZE,file);
    		if(nbByte<=0)
    			break;
     
    		env = send(s,buffer,nbByte,0);
    		if(env==-1){
    			perror("send bloc");
    			exit(-1);
    		}
    		printf("\n données envoyées :%d",env);
    		cumul += nbByte ;
    		bzero(buffer,MAX_SIZE);		
     
    	}while(cumul<taille);
     
    	fclose(file);
     
    	return 0;
    }
    j'attends vos précieuses remarques
    E.BAzOgA

  4. #4
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 876
    Par défaut
    Il y a plusieurs choses genantes dans ton code :

    - tu ne verifies pas combien d'octets ont ete envoyes, tu devrais faire une boucle autour de ton send qui permettrait d'en etre sur. Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    nbByte = fread(buffer,sizeof(char),MAX_SIZE,file);
    	if(nbByte<=0)
    		break;
            env = 0;
            while (env < nbByte) {
                    int tmp;
    	        tmp= send(s,buffer + env,nbByte - env,0);
    	        if(tmp == -1){
    		        perror("send bloc");
    		        exit(-1);
                    }
                    env += tmp;
    	}
    - l'appel a la fonction bzero initialise toutes les cases de ta chaine a 0 je presume, si c'est le cas c'est inutile etant donne que tu envoies a chaque fois un nombre d'octets donnes.

    - je vois pas l'interet de recuperer la taille du fichier si tu ne l'envoies pas au client. Ta condition devrait plutot etre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ((nbByte = fread(buffer,sizeof(char),MAX_SIZE,file)) > 0)
    - (cette remarque n'est pas super utile), pourquoi afficher la meme chose en boucle dans la reception ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("\n reception en cours...sur le socket: %d",s);
    L'id de ta socket ne va pas changer entre temps.

    - ta condition pour la reception des donnees devrait plutot etre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while((nbByte_lu = recv(s,buffer,sizeof(char)*MAX_SIZE,0)) > 0)
    Maintenant quelques conseils que j'aurais a te donner :

    - essaie d'envoyer ton fichier en une seule fois (un read que tu stockes dans un char* puis un send).

    - moins utile mais bon : pareil pour la reception, essaie de faire un seul recv (donc il faudra que tu aies recu la taille du fichier avant).

    Voila, je crois que c'est a peu pres tout...

  5. #5
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    Merci bien "imperio" pour vos remarques:
    Citation Envoyé par imperio Voir le message
    - tu ne verifies pas combien d'octets ont ete envoyes, tu devrais faire une boucle autour de ton send ....
    ===> vu que la fonction send est (generalement) plus rapide que recv, je vois que cela n'est pas necessaire .

    - l'appel a la fonction bzero ....
    ==> ok

    - je vois pas l'interet de recuperer la taille du fichier si tu ne l'envoies pas au client. Ta condition devrait plutot etre :
    ===> pour s'assurer ...,

    - (cette remarque n'est pas super utile), pourquoi afficher la meme chose en boucle dans la reception ?
    ===>Question de débogage, j'ai oublié de nettoyer le code

    - ta condition pour la reception des donnees devrait plutot etre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while((nbByte_lu = recv(s,buffer,sizeof(char)*MAX_SIZE,0)) > 0)
    ===> ceci est équivalent à ce que j'ai fait, mais ta façon est plus lisible

    - essaie d'envoyer ton fichier en une seule fois (un read que tu stockes dans un char* puis un send).
    ===> ce n'est pas une bonne idée.

    E.BaZoGA

  6. #6
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 876
    Par défaut
    Citation Envoyé par bazoga Voir le message
    ===> vu que la fonction send est (generalement) plus rapide que recv, je vois que cela n'est pas necessaire .
    Je crois que tu ne m'as pas compris. La fonction send peut ne pas envoyer toutes les donnees comme demandees car il y aurait des donnees en attente dessus. Ca m'est deja arrive sur de gros transferts. Aucun rapport avec la fonction recv donc.

    Citation Envoyé par bazoga Voir le message
    ===> pour s'assurer ...,
    Precaution inutile.

    Citation Envoyé par bazoga Voir le message
    ===> ce n'est pas une bonne idée.
    La par-contre il va falloir que tu m'expliques en quoi c'est une mauvaise idee. A part si c'est un enorme fichier, c'est la meilleure chose a faire car les appels a read/write sont extremements couteux en temps d'execution.

  7. #7
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    La par-contre il va falloir que tu m'expliques en quoi c'est une mauvaise idee.....
    c'est l'intuition de l'informaticien

    en fait je ne cherche pas une autre solution, je veux juste savoir d'où vient le problème ?

    Client : envoie avec succès les données ==> pas de pb avec send.
    Serveur : l’exécution s'achève dés la première réception.

    Merci pour l'aide.
    E.BaZoGA

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 498
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 498
    Billets dans le blog
    1
    Par défaut
    Il faut utiliser memcheck (de Valgrind) ou dr memory pour avoir une piste sur l'erreur. Une erreur de segmentation, c'est généralement le signe d'une écrire dans une zone non autorisée. 3 possibilités majeures : pointeur non initialisé, pointeur valant NULL, zone réservée trop petite et donc écriture "au delà" de cette zone.

    Je lis ce tutoriel et je vois un -1 qui diffère entre le code présenté par Benjamin Roux et le tien : http://broux.developpez.com/articles...kets/#L3-2-1-c

    memset(buffer,0,sizeof(buffer));
    nbByte_lu = recv(s,buffer,sizeof(char)*MAX_SIZE,0);
    Pourquoi changer de méthode pour calculer la taille de buffer ?

    En compilant le code, je vois un warning sur l'appel à fwrite().

  9. #9
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    voila une faute de frappe à corriger :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nbByte_ecrit = fwrite(buffer,sizeof(char),nbByte_lu,file);
    l'erreur (problème de segmentation) a disparu mais la réception se met en attente (recv), c'est vraiment bizarre, le client est déconnecté donc recv doit retourner 0 (sauf mal compréhension)

    Merci encore une fois.
    E.BAZoGa

  10. #10
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 876
    Par défaut
    Non, c'est bien ca. Si la socket est fermee d'un cote, le recv de l'autre cote doit retourner aussitot. Si recv reste en attente, ca veut dire que la connexion est toujours active.

  11. #11
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    Citation Envoyé par imperio Voir le message
    Non, c'est bien ca. ...
    Merci "imperio" , si tu as le temps, tu peux tester le code

  12. #12
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    876
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 876
    Par défaut
    Citation Envoyé par bazoga
    le client est déconnecté donc recv doit retourner 0 (sauf mal compréhension)
    Je precise que le "non, c'est bien ca" etait pour cette "affirmation".

  13. #13
    Membre confirmé
    Inscrit en
    Novembre 2009
    Messages
    96
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 96
    Par défaut
    Citation Envoyé par imperio Voir le message
    Je precise que le "non, c'est bien ca" etait pour cette "affirmation".
    C'est bien clair

Discussions similaires

  1. envoi mail avec fichier joint
    Par dietrich dans le forum API standards et tierces
    Réponses: 14
    Dernier message: 28/02/2006, 15h42
  2. Script d'envoie d'un fichier excel via un formulaire
    Par Morphine.Nw dans le forum ASP
    Réponses: 4
    Dernier message: 26/01/2006, 14h08
  3. Envoi/Reception de fichier sur un reseau
    Par Janitrix dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 19/12/2005, 15h10
  4. Envoie d'un fichier par Internet
    Par gust dans le forum Access
    Réponses: 7
    Dernier message: 07/12/2005, 16h59
  5. [C#] [FTP] Envoi et suppression fichier sur ftp NON ANONYME!
    Par djsbens dans le forum Windows Forms
    Réponses: 14
    Dernier message: 30/03/2005, 11h20

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