[ C ] Transfert de fichier via socket

Fermé
dr_octopus74 - 29 déc. 2006 à 00:56
daddouna Messages postés 2 Date d'inscription samedi 14 mars 2015 Statut Membre Dernière intervention 30 mars 2015 - 29 mars 2015 à 23:49
Bonjour a tous,
je veux réaliser un envoi de fichier entre client et serveur ,et j'utilise les sockets. Seulement mes connaissances dans ce domaine sont assez limitées.
Les 2 scripts ci-dessous se compilent correctement, mais l'envoi ne fonctionne pas.
Je lance mon programme serveur (qui doit recevoir le fichier) ,ensuite je lance le client ,et sur le serveur j´ai ce message d´erreur: "fseek() :invalid argument".
Par contre, le serveur créer bien un fichier nommé fichier_recv.txt (fichier recu, qui doit etre la copie de celui envoyé),mais evidemment il n'y a rien dedans...

code coté serveur
http://rafb.net/p/kHfqOz75.html

code coté client (qui envoi les données)
http://rafb.net/p/0GoVWw67.html

Pouvez vous m'aider a faire fonctionner ce programme svp ??
A voir également:

11 réponses

kilian Messages postés 8732 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 5 février 2025 1 526
29 déc. 2006 à 04:19
Bonsoir,

Commencons par le fichier serveur.

_Si tu utilises la fonctions exit, il faut appeler le fichier d'en-tête sdtlib.h
Ca s'applique donc à tes deux fichiers sources.

_Ton main ne doit pas être de type void mais de type int. C'est une convention, un programme doit retourner une valeur.

_La fonction fopen, en cas d'echec, ne retourne pas -1 mais retourne NULL.

_ Il ya des soucis avec fseek.
fseek s'utilise comme ceci:
fseek(fichier, adresse, mode d'adessage)
Le mode d'adressage c'est soit SEEK_SET (adressage absolu), SEEK_END (adressage à partir de la fin), SEEK_CUR (adressage relatif => à partir de la position courante)

Et là, tu fais des trucs bizzares avec fseek, du genre:
int fin, pos_fin;
pos_fin = fseek(fichier_dst, fin, SEEK_SET)


Quand tu déclares une variable en faisant "int fin;", cette variable est placée à l'arrache dans la memoire. Et cette zone mémoire a probablement été déjà utilisée auparavant, donc fin prendra la valeur de ce qu'il ya avait avant à cet endroit. C'est donc tout à fait aléatoire ce que tu fais. De même fseek ne retourne pas la nouvelle position du pointeur fichier. Il retourne 0 ou -1.

Si tu veux la position de la fin du fichier, il faut faire (après ça, attention à remettre le pointeur de fichier où il était avant):
int pos_fin;
fseek(fichier, 0, SEEK_END);
pos_fin=ftell(fichier);


De même le fait d'utiliser fseek ne mettra pas des zero là ou il ya du vide dans le fichier. fseek ne fait que déplacer le pointeur du fichier.

_ Attention avec fwrite, tu mets
fwrite(&get_recep, sizeof(char), strlen(get_recep), fichier_dst);

Mais get_recp est de type (char[]). fwrite ne demande qu'un pointeur en premier argument, et toi tu as mis l'adresse d'un tableau (soit un pointeur vers un tableau). Un tableau est déjà un pointeur, donc c'est comme si tu mettais un pointeur vers un pointeur. Met juste fwrite(get_recp,....)

Coté client

Toujours le même problème avec fseek.
Tu fais "fseek (fichier_src, debut, SEEK_SET);"
Tu viens d'ouvrir ton fichier, il pointe déjà vers le début.
D'ailleurs, début est déclaré mais pas initialisé (valeur aléatoire).
Et le début est forcément egal à 0.
Donc met directement la variable current à 0, ça suffira.

_Plus loin tu fais:
while (((nb_lu > 0) && (nb_lu < fin - current)))

Encore une fois, fin est déclaré mais n'est pas initialisé.
Utilise la combinaison fseek/ftell pour avoir la valeur de la fin.
Ensuite, tu peux très bien avoir lu en une fois jusqu'à la fin. Imagine qu'il ya 9 caractères dans ton fichier, tu fais une première lecture, ça donne:
current=0
fin=9
nb_lu=9
Ca ne passera pas la boucle. Fais plutôt:
while (((nb_lu > 0) && (nb_lu <= fin - current)))

Voire même (il ya des parenthèses inutiles):
while ((nb_lu > 0) && (nb_lu < fin - current))


Et voilà.

Si tu fais de la programmation avec socket, je te conseille l'excellent logiciel Wireshark (anciennement ethereal). C'est un sniffeur de paquets réseaux. Ca te permet de savoir si une communication passe bien ou pas, sinon, à quelle moment ça foire et pourquoi etc....
C'est notamment grâce à ça que j'ai pu trouver quelques endroits qui coincent dans ton programme :-)

Un petit bilan avec deux patch. Si tu n'est pas familier avec les patchs, dis toi que les lignes précédées d'un signe "-" sont celles qui ont été supprimées et celles précédées d'un "+" sont celles qui ont été rajoutées (pour remplacer ce qui a été supprimé finalement, donc un "-" sera suivi d'un "+").

Je te le mets sous forme de patch pour que tu puisses localiser les erreurs:
Fichier client:
http://pastebin.bricou.org/419
Fichier serveur:
http://pastebin.bricou.org/420


3
daddouna Messages postés 2 Date d'inscription samedi 14 mars 2015 Statut Membre Dernière intervention 30 mars 2015
29 mars 2015 à 23:49
bonsoir,
j'ai besoin de ces codes sources car j'ai un projet a faire, tu peut m'aider ,
s'il vous plait
j'attend ta reponse
0
/**************************************************************************/
/* CLIENT MESSAGES (domaine Internet, mode connecte , protocole TCP) */
/* */
/**************************************************************************/
#include <stdio.h> /* E/S standard: gets, printf, etc. */
#include <string.h> /* strlen etc. , memcpy */

/* compatibilite */
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h> /* Divers designateurs de type */
#include <sys/socket.h> /* Sockets en general */
#include <netinet/in.h> /* Sockets du domaine Internet */
#include <netdb.h> /* hostent, gethostbyname, gethostbyaddr */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#define closesocket(s) close(s)
#endif

/**************************************************************************/
#define nomhoteserveur "localhost"
#define portserveur 11111
struct sockaddr_in adrserveur; /* Adresse du serveur */
struct sockaddr_in adrclient; /* Adresse du client */
int s; /* Numero socket */
char message[100]; /* Tampon Donnees niveau application */
struct hostent *h;
/**************************************************************************/

static int app (void)
{

/******************** CREATION DE LA SOCKET *****************************/
if ((s = socket (AF_INET, SOCK_STREAM, 6)) == -1) /* 6 = numero protocole TCP */
{
printf (">>> %s\n\n", "Creation socket impossible");
exit (1);
}

/************** INITIALISATION DE L'ADRESSE DU SERVEUR ***************/
adrserveur.sin_family = AF_INET;
if ((h = gethostbyname (nomhoteserveur)) == NULL)
{
printf ("\n>>> %s\n\n", "Nom hote serveur inconnu");
exit (1);
}
memcpy (&adrserveur.sin_addr, h->h_addr, h->h_length);
adrserveur.sin_port = portserveur;

/******** DEMANDE DE CONNEXION ********************************************/
if (connect (s, (struct sockaddr *) &adrserveur, sizeof (adrserveur)) ==
-1)
{
printf ("\n>>> %s\n\n", "Connexion au serveur impossible");
exit (1);
}

/******** EMISSION DU MESSAGE ************************/
char nom[50] = "c:\\fichier_send.txt";
int fin, current;
FILE *fichier_src = fopen (nom, "rb");
if (fichier_src == NULL)
{
perror ("fopen() ");
exit (0); //exit(EXIT_FAILURE);
}

fseek(fichier_src, 0, SEEK_END);
fin=ftell(fichier_src);
/* On se place a l'endroit qui va bien dans le binaire */
fseek (fichier_src, 0, SEEK_SET);
current = 0; /* Détermination de la position courante dans la fichier */

#define BUFSIZE 1024
int nb_lu;
char buffer[BUFSIZE];
memset (buffer, 0, BUFSIZE);
nb_lu = fread (buffer, sizeof (char), BUFSIZE, fichier_src);
int nb_send;
int inc = 1;
while ((nb_lu > 0) && (nb_lu <= fin - current))
{
if ((nb_send = send (s, buffer, nb_lu, 0)) == -1)
{

perror ("send() ");
exit (-1);
}
printf ("nb_send(boucle) \'%d \' = %d\n", inc, nb_send);
if (nb_send == -1)
perror ("send () ");
current = current + nb_lu;
memset (buffer, 0, BUFSIZE);
inc++;
if (fin - current < BUFSIZE)
{
break;
}
else
nb_lu = fread (buffer, sizeof (char), BUFSIZE, fichier_src);
}
memset (buffer, 0, BUFSIZE);
fread (buffer, sizeof (char), fin - current, fichier_src);
if ((nb_send = send (s, buffer, fin - current, 0)) == -1)
{
perror ("write() ");
}
printf ("nb_send = %d\n", nb_send);
fclose (fichier_src);

return 0;
}

int main (void)
{
int ret;
#if defined (WIN32)
WSADATA wsa_data;
int err = WSAStartup (MAKEWORD (2,2), &wsa_data);

if (!err)
{
puts ("WIN: winsock2: OK");
#else
int err;
#endif

err = app ();

#if defined (WIN32)
WSACleanup ();
}
#endif

if (err)
{
ret = EXIT_FAILURE;
}
else
{
ret = EXIT_SUCCESS;
}
return ret;
}
3
dr_octopus74
29 déc. 2006 à 13:06
Franchement merci beaucoup pour ta réponse très détaillée; Elle m'a permis d'y voir un peu + clair sur mon code.
En fait,je ne vois pas trop l'utilité des 2 fseek (ligne 71 et 78) et des variable début et fin, surtout je ne comprend pas trop la phrase "se positionner à la fin entraîne qu'il y aura des 0 partout".

Si j' enleve les fseek et que je met simplement if (( fichier_dst = fopen (titre, "r" )) == -1), le pointeur se placera bien au début du tableau ??
0
kilian Messages postés 8732 Date d'inscription vendredi 19 septembre 2003 Statut Modérateur Dernière intervention 5 février 2025 1 526
29 déc. 2006 à 17:25
Le fseek te permet d'avoir la position de la fin du fichier lorsque tu lis le fichier chez le client.
Ca te permet par la suite de faire:
tant qu'on a pas lu le fichier jusqu'à lafin:
        lire une partie de la suite....


J'ai pas tout corrigé dans tes fichiers.
A un moment tu te positionnes à la fin pour avoir la longueur du fichier. Et après tu te repositionne au début pour lire le fichier. Mais les variables pos_fin et pos_départ ne servent à rien en fait....

Après avoir fait un fopen, si tu ouvres en mode lecture ou écriture ("r" ou "w"), le curseur est déjà au début.
Si tu ouvres en mode ajout ("a" ou "ab"), il se positionnera à la fin.
0
dr_octopus74
31 déc. 2006 à 16:53
Merci beaucoup kilian,j'ai encore un soucis lol,
Comment faire pour que lorsque j'ai fini d'envoyer un fichier au serveur,le script serveur s'arrete.. Pourtant j'ai enlevé tout les exit(-1) de la partie RECEPTION ET AFFICHAGE DES MESSAGES...

Code serveur modifié pour eviter l'arrêt du programme sauf quand le client envoie "exit"
http://rafb.net/p/GnnVh696.html

merci d'avance, bonne année !
0

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

Posez votre question
dr_octopus74
18 janv. 2007 à 13:38
Bonjour, je remet a jour mon post car j'ai un problème pour envoyer le fichier depuis un client WINDOWS vers le serveur (qui lui reste en linux).
Le ping marche bien, la résolution d'hote aussi. Voici mon code client:
Code :


#include <stdio.h> /* E/S standard: gets, printf, etc. */
#include <string.h> /* strlen etc. , memcpy */

/* compatibilite */
#ifdef WIN32
#include <winsock2.h>
#else
#include <sys/types.h> /* Divers designateurs de type */
#include <sys/socket.h> /* Sockets en general */
#include <netinet/in.h> /* Sockets du domaine Internet */
#include <netdb.h> /* hostent, gethostbyname, gethostbyaddr */
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#define closesocket(s) close(s)
#endif

/**************************************************************************/
#define nomhoteserveur "localhost"
#define portserveur 11111
struct sockaddr_in adrserveur; /* Adresse du serveur */
struct sockaddr_in adrclient; /* Adresse du client */
int s; /* Numero socket */
char message[100]; /* Tampon Donnees niveau application */
struct hostent *h;
/**************************************************************************/

int main (void)
{

/******************** CREATION DE LA SOCKET *****************************/
if ((s = socket (AF_INET, SOCK_STREAM, 6)) == -1) /* 6 = numero protocole TCP */
{
printf (">>> %s\n\n", "Creation socket impossible");
exit (1);
}


Pas besoin d'en mettre +, car quand je lance le programme client sur windows, il m'affiche "Creation socket impossible". Il doit donc surement avoir un problème de syntaxe ? Pourriez-vous m'aider SVP ?
0
yyannd Messages postés 44 Date d'inscription mercredi 31 mai 2006 Statut Membre Dernière intervention 2 mars 2007 4
18 janv. 2007 à 13:42
Salut,

Tu pourrais pas copier coller ici tton code serveur et client car les liens ne fonctionnent pas chez moi...Car je veux aussi faire du client serveur mais je comprend rien en syntaxe etc..ou si tu peux me les envoyer en message privée

merci
0
dr_octopus74
18 janv. 2007 à 21:15
tien voici mon msn: dr_octopus74@hotmail.com


Maintenant ,la connexion socket marche, mais quand j'envoi un fichier texte de 3ko, et je me retrouve coté serveur avec un fichier reçu de 20mo ! :s
Voici mon code modifié
http://rafb.net/p/JqzUcR99.html
0
dr_octopus74
19 janv. 2007 à 18:01
salut, j'ai pas trop compris ton message moih.
j'ai testé le programme client sur un windows et le serveur sur linux .(pour ceux qui ne suivait pas, j'ai 2 programmes, un client qui envoi un fichier, et 1 serveur qui recoit ce fichier)
Ca marche pas mal, seulement, a l'arriver ,le fichier recu est en double exemplaire. Exemple ,j'envoi "plouf" et je recoit :
plouf

plouf

Pourtant, sur un analyseur de trame, le fichier est bien envoyé une seule fois... Je pense que c'est donc un probleme au niveau du programme de reception.
Le truc encore + bizarre, c'est qu' avec un client linux, le serveur reçoit bien le fichier comme il faut....

voici mes 2 programmes:
serveur: http://rafb.net/p/jvRUtI99.html
client: http://rafb.net/p/GMWi5e83.html
0
pourrais ai-je avoir ce code dans ma boite mail svp car le lien n'affiche rien: mc_lionnel@yahoo.fr
0
j'ai à réaliser cet exercice "Écrivez un programme Java qui se connecte en TCP à un serveur HTTP, demande une page
HTML" .Mon probleme c comment demader du site de m'envoyer cette page
0
Char Snipeur Messages postés 9813 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 298
21 avril 2008 à 09:48
0
bonjour
est ce que je peut avoi les 2codes (client /serveur )qui permettent de transferer des fichiers .
merci d'avance.
0
on ne sait pas est-ce que on peut voir les deux codes clients serveus puisque on a vraiment besoin à ces code
0