Rechercher : dans
Par :

[ C ] Transfert de fichier via socket

Dernière réponse le 3 nov 2009 à 03:57:38 dr_octopus74, le 29 déc 2006 à 00:56:01 
 Signaler ce message aux modérateurs

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 ??

Meilleures réponses pour « [ C ] Transfert de fichier via socket » dans :
[Shell] Transferer des fichiers via ssh VoirSSH - Secure SHell Utilisation Informations complémentaires LOGICIELS Sous Linux/Unix Sous Windows Avertissement Utilisation SSH permet d'utiliser des pipelines de commandes, et d'utiliser des tubes d'entrées/sorties comme toute...
Discover, le transfert de fichiers en WiFi sur votre iPhone VoirDisponible sur l'App Store depuis le 20 novembre 2008, Discover est une application qui permet l'échange de fichiers du PC vers l'iPhone ou l'iPod Touch. Celle-ci installe un serveur WebDAV sur votre iPod ou iPhone. Simple à utiliser, elle...

1

kilian, le 29 déc 2006 à 04:19:46
  • +2

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


..et le...le...enfin, non parce c'est...ya...quand...bah tu sais là le...

Répondre à kilian

2

dr_octopus74, le 29 déc 2006 à 13:06:43

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 ??

Répondre à dr_octopus74

3

kilian, le 29 déc 2006 à 17:25:19

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.
..et le...le...enfin, non parce c'est...ya...quand...bah tu sais là le...

Répondre à kilian

4

dr_octopus74, le 31 déc 2006 à 16:53:31

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 !

Répondre à dr_octopus74

5

dr_octopus74, le 18 jan 2007 à 13:38:11

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 ?

Répondre à dr_octopus74

6

yyannd, le 18 jan 2007 à 13:42:57

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

Répondre à yyannd

7

dr_octopus74, le 18 jan 2007 à 21:15:10

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

Répondre à dr_octopus74

8

moih, le 19 jan 2007 à 12:55:48

/***********************************************************­***************/
/* 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;
}

Répondre à moih

9

dr_octopus74, le 19 jan 2007 à 18:01:12

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

Répondre à dr_octopus74

14

 Lio23, le 3 nov 2009 à 03:57:38

Pourrais ai-je avoir ce code dans ma boite mail svp car le lien n'affiche rien: mc_lionnel@yahoo.fr

Répondre à Lio23

10

assaad, le 21 avr 2008 à 02:00:52

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

Répondre à assaad

11

Char Snipeur, le 21 avr 2008 à 09:48:41

Regarde le protocole HTTP.
http://www.commentcamarche.net/internet/http.php3 Salutation ! avant je croyais, maintenant je suis fixé.Jésus Christ
Char Snipeur

Répondre à Char Snipeur

12

karim1506, le 1 jun 2008 à 18:56:26

Bonjour
est ce que je peut avoi les 2codes (client /serveur )qui permettent de transferer des fichiers .
merci d'avance.

Répondre à karim1506

13

somia_lmd, le 23 mai 2009 à 23:51:05

On ne sait pas est-ce que on peut voir les deux codes clients serveus puisque on a vraiment besoin à ces code

Répondre à somia_lmd