Code Client/Server et envoi plusieurs fichiers ...

QuakeCoder Messages postés 17 Date d'inscription jeudi 23 novembre 2000 Statut Membre Dernière intervention 10 août 2005 - 5 août 2005 à 13:54
meech Messages postés 209 Date d'inscription vendredi 11 avril 2003 Statut Membre Dernière intervention 14 août 2007 - 8 août 2005 à 11:25
Bonjour,

Après des efforts j'ai réalisé une petite application Client/Server qui sert à
transférer plusieurs fichiers du client vers le serveur. Ca marche impeccable,
mais pas toujours. Parfois le client ne reçoit pas le fichier complet !

Si j’enlève le Sleep(2000) alors un client sur le réseau
et pas sur le même PC ne reçoit pas les memes bytes qu'il doit recevoir ... ou es le probleme dans mon code ?



----- Code Serveur -----




















//variables globales

Char FICHIERS[100][50] ; // tableau des noms des
fichiers

int N ;//nombre des fichiers à transmettre en entier

Char N2[3] ; //nombre des fichiers à transmettre en
char

int TailleFichier;//taille du fichier en entier

char T[10];//taille du fichier en char

Char *buffichier; // buffer memoire, va contenir le fichier

FILE *fich; // Pointeur fichier Source





/* fonction qui lit le continue d’un répertoire et remplit
un tableau nommé char FICHIERS par les noms des fichiers, et une variable N par
le nombre des fichiers. */






ReadDirectory("C:\\Dev-Cpp\\txt\");









//Envoi du nombre de fichiers ...

sprintf(N2,"%d",N);//Conversion de type

if (send(sock2,N2,sizeof(N2),0) < 0) Erreur("Erreur
Transmission du Serveur") ;
















int i=0 ;

while (i < N)

{

//Envoi le nom du fichier

if (send(sock2,fichiers[i],sizeof(fichiers[i]),0) < 0)
Erreur("Erreur Transmission du Serveur !");













if ((buffichier (char *)malloc(10000)) NULL)
Erreur("Reservation Memoire Impossible !");

if ((fich fopen(fichiers[i],"rb")) NULL)
Erreur("Ouverture Fichier Impossible !");

TailleFichier = fread(buffichier,1,10000,fich); // Lecture
dans buffichier

sprintf(T,"%d",TailleFichier);//conversion du int
en char







//Envoi de la taille du fichier

if (send(sock2,T,sizeof(T),0) < 0) Erreur("3:Erreur
Transmission du Serveur !");


















i++ ;//incrementation du conteur

Sleep(2000);

if (send(sock2,buffichier,TailleFichier,0) < 0)
Erreur("Erreur Transmission du Serveur !");

_fcloseall();//
Fermeture Fichier

free(buffichier);//
Libère mémoire

}






----- Code Client -----








//reception du nombre de fichiers

recv(sock,N2,sizeof(N2),0);






N = atoi(N2); //conversion du char en integer














while (i++ < N)

{

//reception du nom
du fichier

char nomfichier[50];

recv(sock, nomfichier,sizeof(nomfichier),0);







if ((fich fopen(nomfichier,"wb"))
NULL) Erreur("Ouverture Fichier Impossible !");









//reception de la taille du fichier

recv(sock,T,sizeof(T),0);









TailleFichier = atoi(T) ; //conversion du char en
integer

if ((buffichier (char *)malloc(TailleFichier)) NULL)
Erreur("Reservation Memoire Impossible !");










//reception du fichier

int receved ;

if ((receved = recv(sock,buffichier, TailleFichier,0)) <
0) Erreur("Erreur Reception du Serveur !");


































if(receved !=
TailleFichier)

{

printf("%d != %d", buffichier, TailleFichier);

Erreur("Erreur Lors du transfert !");

}

fwrite(buffichier,1, TailleFichier,fich);// Ecriture dans FICHIER

free(buffichier);//
Libère mémoire

_fcloseall();//
Fermeture Fichier

}

closesocket(sock);// Fermeture Socket

WSACleanup();//
LIBERATION DLL WINSOCK

6 réponses

meech Messages postés 209 Date d'inscription vendredi 11 avril 2003 Statut Membre Dernière intervention 14 août 2007
5 août 2005 à 15:34
Salut,

Je pense que ça mer[...]ouille à cause de la ligne où tu lis le fichier avec la fonction fread :

TailleFichier = fread(buffichier,1,10000,fich);

Le troisième paramètre de fread spécifie le nombre de blocs à lire dans le fichier. Donc, si la taille du fichier est supérieure à environ 10 000 octets (environ 10 kilo-octets, ce qui est peu), tu ne lis que les 10 premiers kilo-octets et tu abandonnes le reste...

En tout cas, ta variable TailleFichier ne retourne la "bonne" taille du fichier seulement si celle-ci est inférieure ou égale à 10 000 blocs (la fonction fread retournant, sauf en cas d'erreur, le nombre de blocs de données réellement lus).

Ensuite, tu adresses au client le bloc de 10 ko au maximum, ce qui explique que le client ne reçoives pas toujours complètement le contenu du fichier.

La solution consiste à réaliser une boucle où :
1. tu stockes dans un buffer la partie du fichier à lire avec fread ;
2. tu envoies la partie lue au client avec send.

Exemple (en s'adaptant vite fait à ton code)
#define BUFFER_SIZE 1024

// (...)

int length;
while((length = fread(buffichier,1,BUFFER_SIZE,fich)) != 0)
{
if (send(sock2,buffichier,length,0) < 0)
Erreur("Erreur Transmission du Serveur !");
}

En espérant t'avoir aidé un peu,
Ciao.

PS. Documentation sur la fonction fread.
0
QuakeCoder Messages postés 17 Date d'inscription jeudi 23 novembre 2000 Statut Membre Dernière intervention 10 août 2005
5 août 2005 à 16:40
merci pour ta reponse.

bon.le probleme ne viens pas du fread, car noremalent j'ai mis dans le
code (#define FICH_MAX_SIZE 9000000 // Taille Maximum
de Fichier (octets)) 9 mega.

Et tous mes fichiers < 9megas. en plus le programe marche nickel si
je le lance dans le meme poste avec le serveur. j'ai le probleme juste
avec les clients distants !
0
meech Messages postés 209 Date d'inscription vendredi 11 avril 2003 Statut Membre Dernière intervention 14 août 2007
5 août 2005 à 16:51
Sans vouloir te vexer, tu peux
augmenter la taille de ton buffer à 600 millions si tu veux, ce n'est
pas ce qu'il y a de mieux au niveau du code... je te conseille la
boucle avec un buffer plus petit : tu envoies ainsi de petites bribes
de fichier sans saturer ni le client, ni le serveur... Bref, fais comme
tu veux mais, un moment où un autre, tu seras embêter par cela.



Côté client, c'est le même genre de problème :



En fait, rien ne te force à bricoler des histoires de récupération de
taille de fichier : la fonction recv() n'a pas besoin de cela pour
repérer quand elle ne trouve plus aucune donnée en provenance du
serveur. Même solution une boucle : ici, tant que le client reçois
quelque chose c'est à dire tant que :


receved = recv(sock,buffichier, TailleFichier,0))== 0




Fais comme tu veux, mais tu ne trouveras aucun exemple (ou ils ne
seront pas terribles) où le transfert se fait d'un seul bloc. Ce qui
est certain, c'est que des serveurs HTTP (comme Apache ou Microsoft
IIS) n'adresse pas la réponse en un seul morceau... c'est également le
cas des serveurs FTP ou de tout ce qui fonctionne en mode connecté (ie.
socket).



Ciao & bon courage.
0
QuakeCoder Messages postés 17 Date d'inscription jeudi 23 novembre 2000 Statut Membre Dernière intervention 10 août 2005
5 août 2005 à 16:58
oui voila :) . je vais suivre ta procedure et j te repondrai dés que je finis ... merci bq
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
QuakeCoder Messages postés 17 Date d'inscription jeudi 23 novembre 2000 Statut Membre Dernière intervention 10 août 2005
8 août 2005 à 11:07
Bonjour. voila j'ai fais pour le transfert des fichiers ce que vous
m'avez dis.Maintenant c'est bon ... mais ya encore un probleme, parfois
et pas toujours, quand le serveur envoi le nom du fichier à transferer
le client se bug et il recoit une parti du nom et recoit l 'autre parti
quand il recoit la taille du fichier.( voir le code ).



voila.j c pas ou le probleme. dois je faire une boucle aussi pour le transfert du nom du fichier et sa taille ??
0
meech Messages postés 209 Date d'inscription vendredi 11 avril 2003 Statut Membre Dernière intervention 14 août 2007
8 août 2005 à 11:25
Salut,



Je ne pense pas non. Envoie ton code !



PS. Pas la peine de me vouvoyez !!
0
Rejoignez-nous