Script pour envoi de fichier par socket

Script pour envoi de fichier par socket - C - Programmation

Marsh Posté le 27-12-2006 à 17:47:26    

Bonjour, je déplace mon post qui n'etait pas dans la bonne section, avec toutes mes excuses ;)
 
après pas mal de recherche sur le net, je ne trouve rien sur l´envoi de fichier par socket. Pour l´instant j´ai 2 scripts ,1 coté serveur et l´autre coté client, et je peux simplement envoyer des messages du client vers le serveur.
Pourriez vous m´aider svp ? mes connaissances en socket sont assez limités, ce sont des scripts déja faits ...
 
Pour ceux que cela intéresse:
 
CLIENT:
#include <stdio.h>      /* E/S standard: gets, printf, etc.                
#include <string.h>     /* strlen etc. , memcpy                          
#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          
/**************************************************************************/
#define nomhoteserveur "PC_Distant"
#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;
 
/*************************************************
*************************/
 
void main()
{
 
/******************** 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 (bind automatique) ************************/
while (1) /* Boucle sans fin, arret par control-C */
{
 
printf("|Message: " );
gets(message); /* lit une ligne, scanf ne lit qu´un mot */
if (write(s,message,strlen(message)+1) == -1)
{ printf("\n>>> %s\n\n" , "Emission du message impossible" );
exit(1);
}
}
 
 
exit(0);
}
 
 
 
SERVEUR:
 
/**************************************************************************/
/* Fichiers include <....>: consultables par pg ou cat dans /usr/include  */
#include <stdio.h>      /* E/S standard: gets, printf, etc.               */
#include <string.h>     /* strlen etc. , memcpy                           */
#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  
/**************************************************************************/
#define portserveur 11111
struct sockaddr_in adrserveur; /* Adresse serveur */
struct sockaddr_in adrclient; /* Adresse client */
int lgadrclient = sizeof(adrclient);
int s; /* Numero socket */
int cli_sock; /* Numero socket client */
int n; /* Nombre de caracteres lus */
char message[100]; /* Tampon reception niveau application*/
struct hostent *h;
 
/*************************************************
*************************/
void main ()
{
/*********************** CREATION DE LA SOCKET D´IDENTIFIANT s **********/
if ( (s=socket(AF_INET,SOCK_STREAM,6)) == -1 )
{ printf("\n>>> %s\n\n" , "Creation socket impossible" );
exit(1);
}
/*********** LIEN DE LA SOCKET s A L´ADRESSE DU SERVEUR ******************/
adrserveur.sin_family = AF_INET;
adrserveur.sin_addr.s_addr = 0; /* 0.0.0.0 <---> adresse locale */
adrserveur.sin_port = portserveur;
if ( bind(s,(struct sockaddr*) &adrserveur,sizeof(adrserveur)) == -1 )
{ printf("\n>>> %s\n\n" , "Lien de la socket a l´adresse impossible" );
exit(1);
}
 
/******** PASSAGE DE LA SOCKET EN ECOUTE PASSIVE *************************/
printf("Attente de connexion \n" );
/*pause(2);*/
listen(s,10);
 
/******** ACCEPTATION DE CONNEXION ***************************************/
lgadrclient = sizeof(adrclient);
cli_sock = accept(s,(struct sockaddr*) &adrclient,&lgadrclient);
printf("Connexion etablie par le client:\n" );
 
if ( (h=gethostbyaddr((char *) &adrclient.sin_addr.s_addr,
sizeof(adrclient.sin_addr.s_addr),AF_INET)) == NULL)
{ printf("\n>>> %s\n\n" , "Nom hote client inconnu" );
exit(1);
}
printf("|| %s %d\n" , h->h_name , adrclient.sin_port );
 
/******** RECEPTION ET AFFICHAGE DES MESSAGES *************** ***********/
 
while (1)
{
n = read(cli_sock,message,sizeof(message));
if ( n == -1 )
{ printf("\n>>> %s\n\n" , "Lecture du message impossible" );
exit(1);
}
 
printf("|| Client: %s %d\n" , h->h_name , adrclient.sin_port );
printf("|| message: %s\n\n" , message);
}
 
 
}

Reply

Marsh Posté le 27-12-2006 à 17:47:26   

Reply

Marsh Posté le 27-12-2006 à 21:36:29    

bon ok desolé pour ce gros paté de code lol
J´ai trouvé un lien ou une personne a posté un code semblable à ce que je veux faire. J´ai repris ce code du coté de la machine qui DOWNload le fichier.(après je m´attaquerais a la parie UPload)
Voici ce que cela donne:
http://rafb.net/p/U0xIdP80.html
 
J´ai des souci du coté de la variable "cmd" ligne 27
error: ´cmd´ undeclared (first use in this function)
Je ne vois pas ni a quoi elle sert, et surtout comment la déclarer comme il faut...

Reply

Marsh Posté le 27-12-2006 à 22:13:24    

DrOctopus a écrit :

bon ok desolé pour ce gros paté de code lol
J´ai trouvé un lien ou une personne a posté un code semblable à ce que je veux faire. J´ai repris ce code du coté de la machine qui DOWNload le fichier.(après je m´attaquerais a la parie UPload)
Voici ce que cela donne:
http://rafb.net/p/U0xIdP80.html
 
J´ai des souci du coté de la variable "cmd" ligne 27
error: ´cmd´ undeclared (first use in this function)
Je ne vois pas ni a quoi elle sert, et surtout comment la déclarer comme il faut...


 
D'après le code, il semblerait que "cmd" soit une chaîne de caractères contenant le texte "/get" donc un char cmd[5]="/get" mais rien ne garantit cela.
 
Maintenant, ton problème initial serait "l'envoi de fichier par socket". La solution est simple
Coté serveur
- j'écoute le réseau
- dès que j'ai un client, je me forke (j'espère que t'es sous Unixoide) et mon fils lit la socket et enregistre les octets lus dans un fichier tant qu'il y a des octets à lire
 
Coté client
- je crée ma socket et je demande la connexion
- dès que la connexion est active, je lis le fichier par bloc de "n" octets et j'envoie ces "n" octets sur la socket
 
Mais le mieux serait que tu commences par apprendre à utiliser les sockets. Télécharge donc mon cours sur les sockets sous Unix http://fr.lang.free.fr/cours/SocketCsyst_v1.0.pdf et t'auras plus de détails...


Message édité par Sve@r le 27-12-2006 à 22:15:05

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 27-12-2006 à 23:41:09    

Merci bcp,je vais y jeter un coup d'oeil ;)
par contre j'ai encore 2 autre soucis:
1/ comment déclarer la variable titre comprenant le chemin du fichier a télécharger
2/ en compilant j'ai une erreur qui me dit que la variable get_recep n'est pa declaré alors que juste au-dessus il y a: char get_recep[BUFSIZE];
En fait la variable cmd c'est surement pour prevenir le serveur que le client est pret a recevoir les donnees. Quand le serveur recoit cette commande il commence a envoyer le fichier.
Probleme: comment la déclarer ?

Reply

Marsh Posté le 28-12-2006 à 11:25:05    

DrOctopus a écrit :

Probleme: comment la déclarer Comment adapter ce code incomplet auquel je ne comprends rien à un problème en partie identique mais aussi en grande partie différend ?


Solution:  

  • commence par te familiariser avec les sockets - Ecris un exemple simple (ou utilise ceux de mon cours qui sont 100% compilables sous Unix et associés)
  • écris ensuite ton propre code avec ton propre protocole => tu perdras beaucoup moins de temps (ou plutôt  le temps perdu au début sera ensuite regagné 100 fois) et tu auras un truc correct que tu maîtrises parfaitement


Message édité par Sve@r le 28-12-2006 à 11:25:51

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 16:23:33    

merci ;)
bon ca commence un peu a me parler, Il me reste encore des erreurs au niveau du get_recep (ce que je comprend pas car la syntax m'a l'air exact),et à la fin pour la fermeture de la socket...
:108: error: syntax error before ';' token recv.c
:109: error: 'get_recep' undeclared (first use in this function) recv.c
:109: error: (Each undeclared identifier is reported only once recv.c
:109: error: for each function it appears in.) recv.c
:109: error: syntax error before ';' token recv.c
:114: error: syntax error before numeric constant recv.c
:118: error: syntax error before '}' token
 
je vous dispense des warning car yen a pas mal lol
 
voici mon code coté machine qui download
http://rafb.net/p/NyvtnQ36.html
 
PS: get_recep[BUFSIZE] avec ou sans * c la meme chose

Reply

Marsh Posté le 28-12-2006 à 17:15:34    

DrOctopus a écrit :


/**************************************************************************/
/* SERVEUR MESSAGES (domaine Internet, mode connecte  , protocole TCP)    */  
/*                                                                        */
/**************************************************************************/
/* Fichiers include <....>: consultables par pg ou cat dans /usr/include  */
#include <stdio.h>      /* E/S standard: gets, printf, etc.               */
#include <string.h>     /* strlen etc. , memcpy                           */
#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          */
/**************************************************************************/
#define  portserveur    11111
struct sockaddr_in  adrserveur;     /* Adresse serveur                    */
struct sockaddr_in  adrclient;      /* Adresse client                     */
int lgadrclient = sizeof(adrclient);
int     s;                     /* Numero socket                      */
int     cli_sock;             /* Numero socket client               */
int n;                              /* Nombre de caracteres lus           */
char    message[100];             /* Tampon reception niveau application*/
struct hostent     *h;
/**************************************************************************/
void main ()    
{  
 /*********************** CREATION DE LA  SOCKET D'IDENTIFIANT s **********/
if ( (s=socket(AF_INET,SOCK_STREAM,6)) == -1 )      
  { printf("\n>>> %s\n\n" , "Creation socket impossible" );  
    exit(1);  
  }
/*********** LIEN DE LA SOCKET s A L'ADRESSE DU SERVEUR ******************/
adrserveur.sin_family      = AF_INET;
adrserveur.sin_addr.s_addr = 0;   /*  0.0.0.0 <---> adresse locale       */
adrserveur.sin_port        = portserveur;    
if ( bind(s,(struct sockaddr*) &adrserveur,sizeof(adrserveur)) == -1 )  
  { printf("\n>>> %s\n\n" , "Lien de la socket a l'adresse impossible" );  
    exit(1);  
  }
 
/******** PASSAGE DE LA SOCKET EN ECOUTE PASSIVE *************************/
printf("Attente de connexion \n" );
/*pause(2);*/
listen(s,10);
 
/******** ACCEPTATION DE CONNEXION ***************************************/
lgadrclient = sizeof(adrclient);
cli_sock = accept(s,(struct sockaddr*) &adrclient,&lgadrclient);
printf("Connexion etablie par le client:\n" );
 
if ( (h=gethostbyaddr((char *) &adrclient.sin_addr.s_addr,
                        sizeof(adrclient.sin_addr.s_addr),AF_INET)) == NULL)
     { printf("\n>>> %s\n\n" , "Nom hote client inconnu" );  
       exit(1);  
     }
printf("|| %s %d\n" , h->h_name , adrclient.sin_port );
 
/******** RECEPTION ET AFFICHAGE DES MESSAGES  *************** ***********/
 
/*while (1)
  {
   n = read(cli_sock,message,sizeof(message));
   if ( n == -1 )
     { printf("\n>>> %s\n\n" , "Lecture du message impossible" );  
       exit(1);  
     }
 
   printf("|| Client: %s %d\n" , h->h_name , adrclient.sin_port );
   printf("|| message: %s\n\n" , message);
  }*/
int debut, fin;
const char cmd[100] = "serveur pret a envoyer les données";
char titre[50]="\\home\\fichier.txt";
FILE *fichier_dst;
        if (( fichier_dst = fopen (titre, "ab" )) == -1)
        {
                perror("fopen() " );
                exit (-1);
        }
        int pos_depart, pos_fin;
        /* On se place a la fin ce qui mettra des 0 partout la ou */
        /* il y aura du vide                                      */
        if (pos_fin = fseek(fichier_dst, fin, SEEK_SET) == -1)
{
                perror("fseek() " );
                exit(-1);
        }
        printf("On a mis a 0 jusqua le position: %d\n", pos_fin);
        /* On se met au debut du trou afin de remplacer les 0 */
        if (pos_depart = fseek(fichier_dst, debut, SEEK_SET) == -1)
        {
                perror("fseek() " );
                exit(-1);
        }
        printf("On se met a la position de depart: %d\n", pos_depart);
/****************************************************/
        /* Envoie de la commande "/get " au serveur distant */
        /****************************************************/
        if ( send(cli_sock, cmd, sizeof(cmd), 0) == -1)
        {
                perror("reception_liste> write()" );
                exit(1);
        }
/*******************************************/
        /* Écoute de la socket et annalyse de ce   */
        /* qu'envoie le serveur.                   */
        /*******************************************/
#define BUFSIZE 1024;
 int nb_recv=0;
        char *get_recep[BUFSIZE];
        while ( ( nb_recv = recv (cli_sock, get_recep, BUFSIZE, 0)) != 0)
        {
                        fwrite(&get_recep, sizeof(char), strlen(get_recep), fichier_dst);
        }
        fclose(fichier_dst);
        shutdown(cli_sock, 2);
        close (cli_sock);
}



J'ai recopié ton code car ce sera plus simple pour tous les lecteurs. Maintenant, voici les erreurs que j'ai relevées
1) main est de type "int" et pas "void"
2) travailler à partir de variables globales, c'est mal. Je ne vais pas m'étendre là-dessus car le net grouille d'explications à ce propos mais le simple fait de mettre des globales à donf dénote certaines lacunes soit dans la conception du code, soit dans sa compréhension. Ce genre de lacune influe à plus ou moins long terme sur la fiabilité du code...
3) déclarer des variables au moment où on en a besoin, ça fait un peu "fouillis" => même remarque quand à la fiabilité du code qui en ressort
4) je ne comprends pas trop cette histoire de "se positionner à la fin entraîne qu'il y aura des 0 partout". D'ailleurs je ne comprends rien à tes fseek.  
5) tes variables "début" et "fin" ne sont pas initialisée. Or tu t'en sers comme paramètre de tes "fseek". De plus, elles sont inutiles. Si tu veux te mettre au début d'un fichier, tu écrits fseek(fichier, 0L, SEEK_SET);
Si tu veux te mettre en fin de fichier, tu écrits fseek(fichier, 0L, SEEK_END);
 

DrOctopus a écrit :

PS: get_recep[BUFSIZE] avec ou sans * c la meme chose


Absolument. mettre une étoile ou ne pas en mettre donne exactement la même chose. On se demande d'ailleurs pourquoi il y a des étoiles en C...
 
Après ce bref moment de franche hilarité, nous allons revoir ensemble quelques bases
1) tu veux déclarer une zone de travail fixe de "x" octets

char zone[x];


 
2) tu veux déclarer une zone de travail modulable, ou bien dont la taille n'est pas connue à l'avance

char *zone;
zone=malloc(...);    // Allocation
<...>    // Travail
zone=realloc(zone, ...);   // Agrandissement éventuel
<...>   // Retravail
free(zone);         // Libération mémoire


 
Toi, en écrivant "char *get_recep[BUFSIZE]"; tu as déclaré un tableau de "BUFSIZE" <char étoile>; autrement dit un tableau de 1024 pointeurs. Ce n'est absolument pas la même chose qu'un "char get_recep[BUFSIZE]" qui sera un tableau de 1024 octets... ou bien "char *get_recep" qui sera un pointeur destiné à pointer plus tard sur un tableau d'octets. Ta question montrant l'énorme méconnaissance des pointeurs qui sont quand-même une base incontournable du C renvoie de nouveau à la fiabilité finale de ton code...


Message édité par Sve@r le 28-12-2006 à 17:18:46

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 17:55:49    

ok j'avoue, merci en tout cas pour ta réponse très eclairante, je m'en servirai + tard quand mes 2 script seront compilé,mais qu'il ne marcheront pas encore lol.  
 
C bon j'ai rodé le ; apres le define qui coincait pour le script de reception et j'ai enlevé la * qui, il est vrai, ne sert pas.
 
Je me suis maintenant attaqué au fichier d'envoi de donné (bon courage lol)
 
voila mon code apres modif,
http://rafb.net/p/rXMS7P63.html
j'ai des erreur sur la variable buffer, le bzero est-il vraiment indispensable ?
bzero - Ecrire des zéros dans un bloc d'octets.
 
Si oui, Comment regler l'erreur ligne 61 svp ?
:72: error: 'buffer' undeclared (first use in this function)
:72: error: (Each undeclared identifier is reported only once
:72: error: for each function it appears in.)
:61: error: 'buffer' undeclared (first use in this function)
:61: error: (Each undeclared identifier is reported only once
:61: error: for each function it appears in.)
 
Sinon j'ai une tout autre question, comment se fait il que j'ai ces erreurs en compilant avec devc++ ,alors que sous linux elle n'aparait pas ?
25 `AF_INET' undeclared (first use in this function)
pour la ligne
 
 
if ( (s=socket(AF_INET,SOCK_STREAM,6)) == -1)
 
 
j'aimerais pouvoir compiler sur windows, meme si ce script je dois m'en servir sous linux ,c'est lourd de devoir tout le temps redemaré sous linux pour tester. D'ailleur j'avai déja une erreur de ce type avec le script d'envoi
16 invalid application of `sizeof' to incomplete type `sockaddr_in'
pour la ligne suivante:
 
 
  int lgadrclient = sizeof(adrclient);
 
j'ai essayé int lgadrclient = sizeof(struct sockaddr_in); mais rien

Reply

Marsh Posté le 28-12-2006 à 18:17:19    

DrOctopus a écrit :

C bon j'ai rodé le ; apres le define qui coincait pour le script de reception et j'ai enlevé la * qui, il est vrai, ne sert pas est un super gros bug.
 
Je me suis maintenant attaqué au fichier d'envoi de donné (bon courage lol)
 
voila mon code apres modif,
http://rafb.net/p/rXMS7P63.html
j'ai des erreur sur la variable buffer, le bzero est-il vraiment indispensable ?


La fonction "bzero" n'est pas standard donc on ne la trouve pas partout. Moi, quand je veux remplir une zone avec des zéros (ou autre chose), j'utilise "memset()"
Maintenant, si ta question est "est-il indispensable de tout mettre à 0" la réponse est "c'est toi qui voit". Personnellement je n'initialise que ce qu'il faut et jamais plus mais c'est ma façon de faire et cela n'engage que moi. Si t'es assez fort pour maîtriser à 100% le contenu de ton tableau en permanence alors non. Si au contraire t'es pas trop sûr, alors oui... et j'espère qu'un jour t'arriveras à t'en passer. Rappelle-toi juste qu'un tableau d'octets ne devient une chaîne que s'il y a quelque part un octet de valeur '\0'. Si tu recois ce '\0' de ta socket alors il y sera. Si tu ne le reçois-pas, alors t'as quand-même le nombre d'octets reçus donc tu peux le rajouter toi-même au bon endroit...
 

DrOctopus a écrit :

Si oui, Comment regler l'erreur ligne 61 svp ?
:72: error: 'buffer' undeclared (first use in this function)


Ben déclare ta variable "buffer" comme "char buffer[BUFSIZE + 1]"
 

DrOctopus a écrit :

Sinon j'ai une tout autre question, comment se fait il que j'ai ces erreurs en compilant avec devc++ ,alors que sous linux elle n'aparait pas ?
25 `AF_INET' undeclared (first use in this function)
pour la ligne


La programmation C sous Windows est un peu différente que sous Unix. Unix a été écrit en C donc le C va très bien avec Unix. En revanche, le C est une couche rajoutée à Windows qui doit lui-être adaptée et ne l'est pas forcément parfaitement bien. Il est probable que "AF_INET" soit défini dans un header différent sous zindoz et que t'as oublié d'inclure...
 
PS: Je ne comprends toujours pas tes fseek. Si tu veux te mettre au début ce n'est pas la peine car "fopen()" en mode "r" te place déjà au début. De toute façon ta variable "debut" n'est pas initialisée donc sa valeur est indéterminée (sous-entendu tu te places en fait un peu n'importe-où voire même en dehors du fichier)


Message édité par Sve@r le 28-12-2006 à 18:19:43

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 19:03:09    

merci bcp !  
j'ai lu sur un forum qu'il fallait rajouter des .h
 
#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          */
#define closesocket(s) close(s)
#endif
 
mais en résultat, devc++ me redonne plein d'erreur, il doit surement manquer encore qqch...
  [Linker error] undefined reference to `socket@12' ,  `gethostbyname@4' ,  `connect@12' , `send@16'  

Reply

Marsh Posté le 28-12-2006 à 19:03:09   

Reply

Marsh Posté le 28-12-2006 à 19:08:00    

DrOctopus a écrit :

merci bcp !  
j'ai lu sur un forum qu'il fallait rajouter des .h
 
#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          */
#define closesocket(s) close(s)
#endif
 
mais en résultat, devc++ me redonne plein d'erreur, il doit surement manquer encore qqch...
  [Linker error] undefined reference to `socket@12' ,  `gethostbyname@4' ,  `connect@12' , `send@16'


 
Hum non. Apparemment la fonction "gethostbyname" n'existe pas sous zindoz (ou alors elle porte un autre nom). C'est pas vraiment grave, son but est de te renvoyer une IP associée au nom que tu lui donnes. Shunte-là et code l'IP en dur (pour tester)...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 23:09:08    

voila j´ai testé le fonctionnement. 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,mais evidemment ya rien dedans...
Il marque aussi "On a mis a 0 jusqua le position 0" (comme il n´a rien envoyé)
 
code coté serveur
http://rafb.net/p/JYqyrm57.html
 
code coté client (qui envoi les données)
http://rafb.net/p/ntNXam18.html
 
dsl godrik mais les socket ne sont pas ma spécialités, et vu que pour mon projet je dois passer par cette étape (qui est 5% de tout mon projet) j´ai besoin d´aide dans ce domaine. Mais je comprend ta colère et j´en suis désolé

Reply

Marsh Posté le 29-12-2006 à 10:02:10    

DrOctopus a écrit :

j´ai ce message d´erreur: "fseek() :invalid argument"


Relis mes post où j'ai parlé plusieurs fois de "fseek" et des variables non-initialisées que tu lui balançais style "démerde-toi pour me positionner mon fichier où je veux sans que j'ai à te le dire"
 

DrOctopus a écrit :

Par contre, le serveur créer bien un fichier nommé fichier_recv.txt,mais evidemment ya rien dedans...


Evidemment si tu lis rien de ta socket...
 


Qui est "godrik" ???
 

DrOctopus a écrit :

Mais je comprend ta colère et j´en suis désolé


Suis pas en colère. Pour ma part l'étape "fais tes preuves à l'examen ou au concours" est derrière-moi...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-12-2006 à 12:55:10    

lol tu a raison (desolé pr le godrik lol c'est mon cerveau qui était ailleurs) ,  
 
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 ??

Reply

Marsh Posté le 29-12-2006 à 14:17:14    

c bon ca fonctionne enfin !! merci beaucoup sve@r !
maintenant il ne me reste que quelque petite mofification:
*faire marché le programme entre 2 machine distantes (car là je suis sur le  meme pc)
*permettre a plusieurs clients d'envoyer les fichiers sur le meme serveur (je pourrais eventuellement faire autant de script qui se lance qu'il y a de client mais bon c'est un peu lourd je trouve)
*enfin, permettre le fonctionnement sous windows :)
 
Pour ceux que le code intéresse, et si jamais vous avez des conseils
Code client
http://rafb.net/p/ndPBjL18.html
Code serveur
http://rafb.net/p/PhSwyA96.html
 
Merci a sve@r pour sa patience ;)

Reply

Marsh Posté le 29-12-2006 à 14:34:56    

PS: lorsque je compile sous windows ,je met les liens vers les librairies dans Outils/otpions du compilateur/ajouter ces commandes lors de l'appel à l'editeur de liens -----> je met "libws2_32.a -lwsock32 -lwinmm -lmwindows" (je suis sous devc++)
La compilation marche, seulement je n'ai aucun executable en sortie.
Dans le log de compilation, j'ai:
 
gcc.exe "c:\recv.c" -o "C:\recv.exe" -I"C:\Dev-Cpp\include" -L"C:\Dev-Cpp\lib" libws2_32.a -lwsock32 -lwinmm -lmwindows
gcc.exe: libws2_32.a: No such file or directory
Exécution terminée
Compilation OK

Reply

Marsh Posté le 29-12-2006 à 15:09:13    

DrOctopus a écrit :

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


Hum... que de lacunes à combler. J'espère que t'es obligé de programmer ce truc parce que je te vois mal l'écrire pour te faire plaisir...
 
1) un pointeur de fichier de type "FILE *" n'est pas un tableau. C'est comme qui dirait une sorte d'index qui se déplace dans le fichier selon les accès que tu demandes. Et sinon, oui. Lorsque tu ouvres un fichier en mode "r" ou "w", le pointeur est automatiquement mis au début. Lorsque tu l'ouvres en mode "a", le pointeur est automatiquement mis à la fin...
 
2) la fonction "fopen()" qui échoue renverra NULL. La fonction "fopen()" qui réussit renverra la valeur du pointeur de fichier correspondant. Cette valeur peut être "0xffff" (donc "-1" en signé) ou bien une autre valeur quelconque (mais pas nulle). Je ne comprends donc pas pourquoi tu vas vérifier que "fopen()" a renvoyé "-1"

if ((fichier_dst=fopen (titre, "r" )) != NULL)


 

DrOctopus a écrit :

c bon ca fonctionne enfin !! merci beaucoup sve@r !
maintenant il ne me reste que quelque petite mofification:
*faire marché le programme entre 2 machine distantes (car là je suis sur le  meme pc)


En ligne 42 de ton client, tu récupères l'adresse du serveur par son nom puis tu utilises cette adresse pour remplir la variable "adr_serveur" donc je vois pas où est le problème. Ce client fonctionnera que tu sois sur la même machine ou sur une machine distante. En fait, le client ne sait même pas qu'il est sur la machine du serveur car tout se passe exactement comme s'il était à distance
 

DrOctopus a écrit :

*permettre a plusieurs clients d'envoyer les fichiers sur le meme serveur (je pourrais eventuellement faire autant de script qui se lance qu'il y a de client mais bon c'est un peu lourd je trouve)


Si t'es sous unix, pas de problème. Dès que le serveur reçoit un appel, il lance un fils via "fork()". Le fils hérite de la socket donc il peut dialoguer avec pendant que le père se remet en écoute d'un autre appel.
Sous zindoz, beaucoup plus compliqué vu que zindoz ne connait pas le "fork()" (je ne suis même pas certain que zindoz connaisse le multi-processus)
Pourquoi tu regardes pas mes exemples simples de client/serveur ? Ils sont totalement compatibles unix. Le client appelle le serveur, fait saisir une chaîne et l'envoie au serveur qui l'affiche. Et le client continue tant qu'on ne saisit pas "EOT". Et le serveur fonctionne pour un nombre théoriquement infini de clients s'adressants à lui en parallèle...
En plus, transformer mon client qui envoie une chaîne saisie au clavier en un client qui envoie un fichier c'est pas vraiment difficile. Idem pour le serveur qui affiche ce qu'il reçoit mais qui pourrait l'enregistrer dans un fichier...
 

DrOctopus a écrit :

*enfin, permettre le fonctionnement sous windows :)


Là je dis "bravo... beau challenge" !!!
 

DrOctopus a écrit :

Merci a sve@r pour sa patience ;)


Tu veux sans-doute dire "mon infinie patience"...
Pas de pb. .. :sol:  
 


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-12-2006 à 15:33:32    

Sve@r a écrit :

1) un pointeur de fichier de type "FILE *" n'est pas un tableau. C'est comme qui dirait une sorte d'index qui se déplace dans le fichier


Pas du tout. FILE est un type abstrait qui définit un fichier. On ne sait pas ce qu'il y a dedans et sa valeur est définie par fopen(). Cette valeur ne change évidement pas pebndant ls manipulations (comment pourrait-elle changer, vu qu'on ne fait que passer la valeur au fonction et jamais l'adresse du pointeur...). C'est un pointeur sur un certain contexte de fonctionnement. C'est tout.
 

Citation :

En ligne 42<...>


[:arrakys]  


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-12-2006 à 17:20:59    

Emmanuel Delahaye a écrit :

Pas du tout. FILE est un type abstrait qui définit un fichier.


Si c'est un type abstrait, je peux en faire l'abstraction schématique (représentation simplifiée de l'abstraction) qui me convient. Et si je veux me le représenter par un index...
Certes sa valeur ne change jamais... mais comme il pointe vers une structure, rien n'empêche les membres de la structure pointée de changer eux !!!


Tiens ? j'ai raté quelque chose en ligne 42 ??? Honnêtement je ne vois rien de choquant à récupérer la zone statique renvoyée par "gethostbyname" puis recopier immédiatement les infos qui m'intéressent dans une "struct sockaddr_in". Evidemment dans un contexte multi-thread cela deviendrait plus dangereux (une même zone statique utilisée par plusieurs thread en parallèles) mais on n'en n'est pas encore là. D'ailleurs vive le "fork()" qui isole parfaitement les contextes des différents processus et "a bas le thread()" qui va utiliser un seul contexte commun pour tout le monde !!!

Message cité 1 fois
Message édité par Sve@r le 29-12-2006 à 17:29:50

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-12-2006 à 17:48:13    

Sve@r a écrit :

Tiens ? j'ai raté quelque chose en ligne 42 ???


C'est le triangle des Bermudes de l'informaticien...
 
http://groups.google.fr/groups?q=l [...] F-8&tab=wg
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 29-12-2006 à 18:03:49    

Citation :


Si t'es sous unix, pas de problème. Dès que le serveur reçoit un appel, il lance un fils via "fork()". Le fils hérite de la socket donc il peut dialoguer avec pendant que le père se remet en écoute d'un autre appel.
Sous zindoz, beaucoup plus compliqué vu que zindoz ne connait pas le "fork()" (je ne suis même pas certain que zindoz connaisse le multi-processus)
Pourquoi tu regardes pas mes exemples simples de client/serveur ? Ils sont totalement compatibles unix. Le client appelle le serveur, fait saisir une chaîne et l'envoie au serveur qui l'affiche. Et le client continue tant qu'on ne saisit pas "EOT". Et le serveur fonctionne pour un nombre théoriquement infini de clients s'adressants à lui en parallèle...
En plus, transformer mon client qui envoie une chaîne saisie au clavier en un client qui envoie un fichier c'est pas vraiment difficile. Idem pour le serveur qui affiche ce qu'il reçoit mais qui pourrait l'enregistrer dans un fichier...


 
j'ai regardé ton script qui utilisait fork() (Communication en AF_UNIX). Peux tu m'expliquer la différence entre sk_create et sk_dialog? sk_dialog c'est la socket sur laquelle communique client et serveur ? et l'autre ?
C'est quelque chose que j'ai pas compris en général sur les socket (sk_create et sk_dialog sont respectivement les équivalents sur mon code des sockets s et cli_sock ?)  

Code :
  1. /* Création socket */
  2. if ((sk_creat=socket(AF_UNIX, SOCK_STREAM, 0)) == (-1))
  3. {
  4. fprintf(stderr, "ligne %u - socket() - %s\n", __LINE__, sys_errlist[errno]);
  5. exit(errno);
  6. }


 

Code :
  1. /* Attente connexion client */
  2. if ((sk_dialog=accept(sk_creat, NULL, NULL)) == (-1))
  3. {
  4. fprintf(stderr, "ligne %u - accept() - %s\n", __LINE__, sys_errlist[errno]);
  5. exit(errno);
  6. }


a part ca je pense avoir a peu près compris le ofnctionnement du fork()  
je vais encore me pencher dessus, merci en tout cas ;)

Reply

Marsh Posté le 29-12-2006 à 18:12:51    

c'est bon j'ai pigé mon message précédent (desolé question bête),
mon nouveau script va donc se présenter un peu comme ca ?

Code :
  1. /* Duplication du process */
  2. switch (pid=fork())
  3. {
  4. case (-1): /* Erreur de fork */
  5. close(s);
  6. close(cli_sock);
  7. fprintf(stderr, "ligne %u - fork() - %s\n", __LINE__, sys_errlist[errno]);
  8. exit(errno);
  9. case 0: /* Fils */
  10. /* Fermeture socket inutilisée */
  11. close(s);
  12. /* Lecture en boucle sur la socket */
  13. ici j'implante mon code de reception de fichier
  14. /* Si l'arrêt de la lecture est dû à ne erreur */
  15. if (sz_read == (-1))
  16. {
  17. close(sk_dialog);
  18. fprintf(stderr, "ligne %u - read() - %s\n", __LINE__,
  19. sys_errlist[errno]);
  20. exit(errno);
  21. }
  22. /* Fin du fils */
  23. close(sk_dialog);
  24. exit(0);
  25. default: /* Père */
  26. close(sk_dialog);
  27. }


 
Seulement quelque chose me chiffone, au niveau de la création du fichier de reception. Comment est-ce que le fils va creer un fichier différent a chaque fois ? fichier_recv1.txt pour la 1er client ,fichier_recv2. txt pour le 2eme client,etc...
Boucle ?

Reply

Marsh Posté le 29-12-2006 à 18:27:22    

Emmanuel Delahaye a écrit :

C'est le triangle des Bermudes de l'informaticien...
 
http://groups.google.fr/groups?q=l [...] F-8&tab=wg


EXCELLENT !!! Je ne connaissais absolument pas cette aréa 51  :sol:  
 

DrOctopus a écrit :

j'ai regardé ton script qui utilisait fork() (Communication en AF_UNIX). Peux tu m'expliquer la différence entre sk_create et sk_dialog? sk_dialog c'est la socket sur laquelle communique client et serveur ? et l'autre ? C'est quelque chose que j'ai pas compris en général sur les socket


C'est pas vraiment compliqué. En fait, le protocole de mise en communication impose plusieurs étapes
1) il te faut une socket de départ qui est totalement abstraite. Elle sert juste à identifier ton host, ton protocole et autres généralités sur le réseau. C'est cette socket qui écoute le réseau et attend le client
2) une fois le client accepté, il te faut un second item différent du premier qui identifie juste le tube servant au transfert de données. C'est ce que j'ai nommé "socket de dialogue".
Pour bien imager le concept, c'est comme pour un téléphérique. Tu as un premier cable qui sert de support au téléphérique, et un second cable qui sert à le tirer dans un sens ou dans un autre (je pense à ça car j'ai regardé "Moonraker" hier soir et il y a un passage avec un téléphérique au dessus de Rio).
Maintenant j'ai écrit ce cours en 1999 et si je devais le mettre au goût du jour, j'utiliserais une structure pour regrouper les deux item (car conceptuellement, l'un ne va pas sans l'autre)...
 

DrOctopus a écrit :

a part ca je pense avoir a peu près compris le fonctionnement du fork()  
je vais encore me pencher dessus, merci en tout cas ;)


Pour plus de détails sur fork, voir  http://fr.lang.free.fr/cours/Processus_Csyst_v1.0.pdf et bien entendu l'inévitable "man"...
 

DrOctopus a écrit :

Seulement quelque chose me chiffone, au niveau de la création du fichier de reception. Comment est-ce que le fils va creer un fichier différent a chaque fois ? fichier_recv1.txt pour la 1er client ,fichier_recv2. txt pour le 2eme client,etc...
Boucle ?


Aucun soucis. Chaque fils est associé à un client (donc "n" clients => "n" fils) et chaque client commence par envoyer le nom du fichier à créer. Donc le rôle du fils est de 1) recevoir un seul nom de fichier 2) recevoir des octets 3) mettre ces octets dans le nom demandé. 4) se terminer proprement. Aucune boucle...
Eventuellement un risque de conflit si deux clients différents demandent à créer le même fichier (style "/etc/passwd" ) mais ce conflit peut se résoudre de différentes manières dont la première qui me vient à l'idée est d'associer à chaque client un répertoire bien à lui => le fichier "/etc/passwd" du client 1 ira se loger dans "client1/etc/passwd" et etc...


Message édité par Sve@r le 29-12-2006 à 19:22:00

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 29-12-2006 à 20:36:24    

DrOctopus a écrit :


Seulement quelque chose me chiffone, au niveau de la création du fichier de reception. Comment est-ce que le fils va creer un fichier différent a chaque fois ? fichier_recv1.txt pour la 1er client ,fichier_recv2. txt pour le 2eme client,etc...


Tu es censé implémenter un protocole minimum qui passe le nom et la taille du fichier...


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 30-12-2006 à 00:08:27    

Oula je suis pas d'accord avec vous là. D'accord chaque client a son propre fichier a envoyé .Mais le serveur,lui, n'a qu'un seul fichier destination nommé fichier_recv... En effet ,lorsqu'un client envoi son fichier_send, le serveur copie ce fichier, et ecrit son contenu dans un fichier nommé fichier_recv.
3) mettre ces octets dans le nom demandé. 4) se terminer proprement. Aucune boucle...  
 
Donc c'est dans le fork() qu'il faudra que je mette la création du fichier fichier_recv si j'ai bien compris ? La forme du code que j'ai mis au dessus est-elle correct ? surtout la ligne 14, est-ce ici que je doit implanté mon code de download du fichier ?

Reply

Marsh Posté le 30-12-2006 à 10:46:29    

DrOctopus a écrit :

Oula je suis pas d'accord avec vous là.


C'est tout à fait normal. C'est parce nous on a raison et que toi t'as tord. Mais t'inquiète pas, tu t'y feras vite [:ddr555]
 
En fait on ne lis pas complètement ton code en détail ni le détail de ton protocole. A un moment j'ai vu que tu parlais du "nom du fichier" donc j'ai pensé que ton client commençait par envoyer le nom du fichier au serveur et que le serveur utilisait ce nom comme nom du fichier à créer. Mais si c'est pas ça c'est pas grave. Tu écrits ton protocole comme tu en as envie. Si le serveur place les octets reçus dans un fichier avec un nom "standard" il faut donc que ce nom soit évidemment unique pour chaque client donc que tu lui associes un identifiant du client (par exemple son n° IP)
 

DrOctopus a écrit :

D'accord chaque client a son propre fichier a envoyé .Mais le serveur,lui, n'a qu'un seul fichier destination nommé fichier_recv... En effet ,lorsqu'un client envoi son fichier_send, le serveur copie ce fichier, et ecrit son contenu dans un fichier nommé fichier_recv.


Pas tout à fait - Il faut impérativement que le nom du fichier prenne en compte l'identifiant du client. En fait, pour bien finaliser ton projet, il faut que tu te poses les questions suivantes
1) avec combien de clients distincts mon serveur devra dialoguer en parallèle ?
2) combien de fois chaque client a le droit d'envoyer des fichiers ou bien combien de fichiers un client peut envoyer ?
Et évidemment finaliser ton protocole déjà dans ta tête pour bien répondre à ces questions...
 

DrOctopus a écrit :

Donc c'est dans le fork() qu'il faudra que je mette la création du fichier fichier_recv si j'ai bien compris ?


Presque. C'est dans la partie du code où "fork()" a renvoyé 0 car c'est là que le fils bosse. Dans le multi-processus c'est le point le plus dur à comprendre: Au moment où le "fork" s'exécute tout le code situé sous le fork est dupliqué dans un 2° processus qui va s'exécuter en parallèle du premier. Et la seule façon de différencier si on est dans le processus 1 (le père) ou le processus 2 (le fils) est dans la valeur renvoyée par le fork qui vaut 0 dans le procesus fils et le pid du processus fils dans le processus père...
 

DrOctopus a écrit :

La forme du code que j'ai mis au dessus est-elle correct ? surtout la ligne 14, est-ce ici que je doit implanté mon code de download du fichier ?


Tout à fait !!!


Message édité par Sve@r le 30-12-2006 à 10:46:58

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 31-12-2006 à 15:45:43    

oki! avant de me lancer dans le fork(), j'avais une derniere question. 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
 
Aussi j'ai une autre question, au niveau du fork, dans la partie case(0) du fork, je ne met que la partie RECEPTION ET AFFICHAGE DES MESSAGES ? et non toute ma procédure principale (création de socket,acceptation de connexion,etc...) ?
d'avance merci, et bonne année ;)
 

Reply

Marsh Posté le 01-01-2007 à 00:43:58    

DrOctopus a écrit :

oki! avant de me lancer dans le fork(), j'avais une derniere question. Comment faire pour que lorsque j'ai fini d'envoyer un fichier au serveur,le script serveur s'arrete..


Ben justement le principe d'un serveur avec fork est de ne jamais s'arrêter pour pouvoir répondre à tout nouveau client qui cherche à le contacter. Dès qu'un nouveau client se connecte il crée un fils qui prend en charge la partie "transmission" pendant que lui, le serveur, se remet en attente d'un autre client. Et ainsi de suite...
Une fois que le fils ne lit plus rien (parce que le client à fini), il se termine simplement sur "exit" et disparaît du système.
 
Si tu veux un simple serveur destiné à seulement "n" clients et pas plus, alors pas besoin de fork. Tu fais un "listen(..., n)" et tes "n" clients seront mis en attente. Puis tu les traites un à un dans une boucle puis tu t'arrêtes et t'as fini.
 

DrOctopus a écrit :

Aussi j'ai une autre question, au niveau du fork, dans la partie case(0) du fork, je ne met que la partie RECEPTION ET AFFICHAGE DES MESSAGES ? et non toute ma procédure principale (création de socket,acceptation de connexion,etc...) ?


Evidemment puisque le fils est lancé une fois la connexion acceptée et qu'il hérite d'une copie de tout ce qui a été créé par le père (les variables, les descripteurs de fichiers, les sockets, etc). C'est d'ailleurs pour ça que dans le fils il faut fermer la socket de connexion car elle aussi a été copiée alors qu'elle lui est inutile.
Faudrait vraiment que tu lises les docs qu'on te fournit...


Message édité par Sve@r le 01-01-2007 à 11:41:54

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 01-01-2007 à 22:27:16    

oki merci de ta réponse :)
par contre j'ai toujours pas compris pourquoi est-ce que mon programme s'arrete alors que je lui ai pas mis de exit(-1)...

Reply

Marsh Posté le 02-01-2007 à 13:51:07    

DrOctopus a écrit :

oki merci de ta réponse :)
par contre j'ai toujours pas compris pourquoi est-ce que mon programme s'arrete alors que je lui ai pas mis de exit(-1)...


Euh... je sais pas (ton lien posté plus haut n'est pas valide). T'as bien mis ton corps "accept/fork" dans un "while(1)" ???


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 02-01-2007 à 15:34:27    

Sve@r a écrit :


Qui est "godrik" ???


 
Pour savoir qui est ce mysterieux Godrik rendez vous sur http://www.jeuxvideo.com/forums/1- [...] -1-0-0.htm  
DrOctopus, ne serait il pas plus profitable pour toi d'apprendre par toi meme plutot que d'être dépendant de la bonne volontée des autres ?

Reply

Marsh Posté le 02-01-2007 à 18:53:43    

KouicKouic a écrit :

Pour savoir qui est ce mysterieux Godrik rendez vous sur http://www.jeuxvideo.com/forums/1- [...] -1-0-0.htm


[:rofl]


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 02-01-2007 à 19:47:56    

lol je suis démaské,
nan mais je pensais que ça irai vite car je ne pensais pas que le domaine des socket etait aussi dense :). Donc a chaque probleme ,je me disais "bon ca doit pas etre très dure pour des personnes qui s'y connaisse bien... je ne pensais pas qu'on allait faire une enquete sur mon cas KouicKouic lol.
En tout cas j'ai appris pas mal sur les socket si tu veux savoir, et ce en partie grace à svear ;) Mais là mon dernier soucis je ne sais pas comment le regler,et je pense pas qu'un cours sur les sockets ne me le regle... désolé
 
Pour ceux que cela intérèsse...
http://rafb.net/p/A7FwsQ67.html
 
Pour te répondre svear, je n'utilise toujours pas le fork, j'essai juste de permettre un envoi continu de fichier depuis le client (que le serveur ne s'arrete jamais quoi :))

Reply

Marsh Posté le 02-01-2007 à 20:15:06    

Désolé j'ai sans odute parlé un peu vite sur le cours sur les sockets lol.
Je pense qu'il faut rajouter un while (1) quelque part, mais le faut-il simplement 98 pour l'ecriture dans le fichier fichier_dst, ou carement ligne 60 pour toute la procédure principale ? :)

Reply

Marsh Posté le 02-01-2007 à 20:49:30    

Ne t'inquiete pas DrOctopus, il n'y as pas de mal a demander de l'aide sur les forums, ils sont fait pour cela. De plus je suis sur que les personnes qui ont répondu l'on fait avec plaisir, dans le cas contraire il l'auraient fait savoir. Néanmoins je te voyais effectivement t'enfoncer dans une succession de questions, une reponse en appelant une nouvelle. Avec plus de pratique dans le langage C et quelques tutoriaux sur les sockets tu aurais gagner beaucoups de temps, beaucoups plus de connaissances et d'indépendance.
 
Kouic 'Big Brother' Kouic.

Reply

Marsh Posté le 03-01-2007 à 00:53:41    

oui tu as raison, mais en tout cas je pense avoir acquis pas mal de choses,d'autant plus que maintenant je vais revoir un peu différents cours pour améliorer mon programme,et ca va rouler :)
en tout cas merci a tous, et surtout a sve@r
 
PS: j'ai résolu le souci de la boucle infini ;)

Reply

Marsh Posté le 03-01-2007 à 10:30:31    

DrOctopus a écrit :

j'essai juste de permettre un envoi continu de fichier depuis le client (que le serveur ne s'arrete jamais quoi :))


Ben je vais résumer ton serveur
- création socket
- création d'une file d'attente pour 5 clients max
- acceptation du premier client de la file
- lecture fichier
- fin
 
T'aurais pas l'impression qu'il manque un truc... attend, le mot m'échappe... un truc qui tourne... ah oui, une boucle !!!  :sol:  
 

DrOctopus a écrit :

Désolé j'ai sans doute parlé un peu vite sur le cours sur les sockets lol.
Je pense qu'il faut rajouter un while (1) quelque part, mais le faut-il simplement 98 pour l'ecriture dans le fichier fichier_dst, ou carement ligne 60 pour toute la procédure principale ? :)


Vas-y Maïté, fais-nous ta recette. Un peu de ceci en ligne 58, un peu de cela en ligne 60. Je mélange, fais cuire et hop...  :sol:  
Faut pas faire un prog C comme la potion de Panoramix... Faut d'abord découper ton problème en tâches élémentaires de façon à ce que l'ensemble des opérations résolve ton problème (algo) puis transcrire ton algo en C...
 
 
Sinon, pour répondre à ta question, la boucle doit commencer sur le "accept". C'est lui qui autorise le client à se connecter sur ta socket...
Algo:
- création de la socket
- création de la file d'attente
- tant que condition quelconque (là faut un peu essayer de voir mais j'ai franchement pas envie de réfléchir ce matin donc c'est toi qui t'y colles - Peut-être "while (accept(...))", je sais pas trop - Faut regarder si "accept()" peut arrêter la boucle...)
- faire
   - acceptation client (sauf si le "accept()" est dans le while)
   - lecture fichier envoyé par client (là c'est aussi une boucle de lecture donc il y aura 2 boucles au total => tu t'en sortiras ???)
- fin faire
- fin pgm
 
PS: Evite les globales. Pas beau !!!


Message édité par Sve@r le 03-01-2007 à 10:38:59

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 03-01-2007 à 16:14:59    

okay tin c'est assez tendu quand même.  
Je ne sais pas exactement combien de clients vont se connecter a mon serveur. Au départ j'avais pensé à une structure simple du type:
- création de la socket
- création de la file d'attente (dans le 0 du fork)
        - acceptation client  
        - lecture fichier envoyé par client ; 2 solutions:
 
* écriture du fichier reçu selon le numéro du client dans la file d'attente (ex: fichier_recv1, fichier_recv2) donc besoin d'une boucle. C'est là tout mon probleme car je ne vois pas quel type boucle il faut réaliser pour que le fichier recu soit écrit en fonction du client qui l'envoie...
 
* autrement (solution plus pratique je pense) en fonction du numéro de uid...Ici je ne vois pas pourquoi il faudrait une boucle étant donné que c'est le processus fils qui va creer les fichiers les uns après les autres... (dans la file d'attente). Les fichiers ainsi crées seront obligatoirement différents...
 
 
 

Reply

Marsh Posté le 03-01-2007 à 16:43:03    

DrOctopus a écrit :

Je ne sais pas exactement combien de clients vont se connecter a mon serveur.


On s'en fout. Tu prévois ta file d'attente pour "n" clients ("listen(..., n)" ). Les premiers peuvent entrer, les autres restent dehors jusqu'à ce qu'une place se libère (pour eux, le "connect()" est refusé et ils doivent retenter plus tard...).
 
Faut que tu arrives à schématiser ton serveur comme un cabinet d'attente chez le médecin. Le médecin a une salle d'attente prévue pour "n" clients (c'est le listen() qui crée la salle d'attente). Il les reçoit un par un (boucle sur le "accept()" ) et à chaque siège qui se libère dans la salle d'attente un autre client peut venir s'asseoir (le "connect()" du client). Ensuite, faut distinguer avec ou sans fork
- sans fork, le père s'occupe de tout. Il récupère ce que le premier client lui raconte pendant que les autres patientent (donc les autres sont acceptés mais pour eux, rien ne se passe puisqu'on ne s'occupe pas d'eux). Puis le premier client a terminé, le second prend sa place et le serveur s'occupe de lui pendant que les autres patientent encore. Puis ...
- avec fork, le père crée un clone de lui-même (comme si le médecin se dupliquait) et le clone s'occupe immédiatement du client. Comme le père est libre, il peut faire entrer un second client de suite et créer un clone de nouveau pour le second client et faire entrer le 3° client de suite etc... donc la salle d'attente est toujours vide (d'où le "listen(..., 1)" de mon exemple)
 

DrOctopus a écrit :

* écriture du fichier reçu selon le numéro du client dans la file d'attente (ex: fichier_recv1, fichier_recv2) donc besoin d'une boucle. C'est là tout mon probleme car je ne vois pas quel type boucle il faut réaliser pour que le fichier recu soit écrit en fonction du client qui l'envoie...


Effectivement... car chaque client accepté est unique. Mais qu'est-ce qui t'empêche d'avoir un indice qui s'incrémente à chaque "accept()" ??? Le fils récupèrera aussi une copie de cet indice au moment de sa création donc chaque client aura un n° unique...
 

DrOctopus a écrit :

* autrement (solution plus pratique je pense) en fonction du numéro de uid...Ici je ne vois pas pourquoi il faudrait une boucle étant donné que c'est le processus fils qui va creer les fichiers les uns après les autres... (dans la file d'attente). Les fichiers ainsi crées seront obligatoirement différents...


Oui pour la boucle. Le fils n'a pas besoin de boucle puisqu'il ne s'occupe que d'un seul client. C'est le père qui fait sa boucle sur le "accept()" (voir mon exemple sur mon tuto).
Mais en ce qui concerne le pid => bad idea. En effet, rien n'empêche aujourd'hui un pid terminé d'être réutilisé pour un nouveau process. Donc le client 1 arrive (pid=100). Puis le 2 arrive (pid=200). Puis le 1 se termine (pid=100 libre). Puis le 3 arrive (pid=100).
Avant, un pid mort n'était plus jamais réutilisé (=> reboot périodique obligatoire) mais plus maintenant...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 03-01-2007 à 17:52:55    

ok merci, donc c'est pas bon pour le uid.  
 
Tu as dit: "un indice qui s'incrémente à chaque "accept()""
Je ne vois pas comment réaliser le lien entre la connexion d'un client différent et l'indice dont tu m'a parlé au-dessus. Car si j'arrive à avoir un indice différent pour chaque client,je n'ai plus qu'a l'utiliser pour différencier les noms des fichiers recus (ex: fichier_recv &indice)
 
Forme de la structure:
-Père
accepte un client  
indice = n
-Fils  
accepte un client  
indice = n+1
 
En bref: quel structure C peut me permettre qu'a chaque fois qu'on appelle accept(),on incrémente l'indice ?
 
merci pour ton aide :)
 

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed