Reseau Socket - Problème de bind() dans un client/serveur local

Reseau Socket - Problème de bind() dans un client/serveur local - C - Programmation

Marsh Posté le 27-10-2004 à 11:56:34    

Salut a tous,
 
Je suis sur un projet de client/serveur ftp en C sous unix. Je le teste en local pour le moment. Je suis débutant en réseau et il s'agit d'un projet basique.
J'essaye de faire passer un fichier du serveur vers le client, à partir d'un fichier source sur le serveur.
 
Lorsque je lance le client, tout se déroule normalement (en tout cas apparament)
 
Mais lorsque Je veux renouveller l'opération (après avoir closé le socket, le fichier, effacé le fichier copié etc...) ca ne fonctionne plus.
Le bind ne marche plus !
 
Si quelqu'un connait différentes raisons qui peuvent amener a un plantage du bind, merci de me tenir au courant ca me serait tres utile !
 

Reply

Marsh Posté le 27-10-2004 à 11:56:34   

Reply

Marsh Posté le 27-10-2004 à 12:07:04    

Piper1664 a écrit :

merci de me tenir au courant ca me serait tres utile !

tu veux pas plutôt filer des messages d'erreurs ? et pourquoi tu fais 36 bind dans ton programme ? t'as fait des vérifications d'erreur, utilise perror, etc :o

Reply

Marsh Posté le 27-10-2004 à 12:11:12    

Non en réalité je ne fais qu'un bind. Ce que je veux dire, c'est qu'après avoir arreté le serveur puis redémarré, la le bind ca marche plus.
Je n'ai pas de message d'erreur a part mon printf perso (apres renvoit -1).
je veux bien filer mes messages d'erreur mais je sais pas comment on fait pour utiliser perror ? sinon j'avais vu que le bind utilisait bgerror. c'est pareil ? comment on l'utilise stp ?
 
merci bcp !!

Reply

Marsh Posté le 27-10-2004 à 12:31:04    

setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
 
man perror :o

Reply

Marsh Posté le 27-10-2004 à 12:54:01    

ok merci.
 
Alors perror me renvoit "address already in use"
[j'ai mis perror(bind) mais jsuis pas sur que ce soit la bonne syntaxe. je comprend pas trop quel est l'argument a mettre (char * include the name of the function...)]
quand je quitte le serveur, je fais un close(sock).
Il faut peut etre libérer l'adresse du bind mais jsais pas trop de laquelle il s'agit et de comment on fait.
 
qu'en penses tu ?  
 
merci d'avance
 
P.S : a koi sert setsockopt (j'ai maté avec man mais jpige pas trop l'intéret) :-S

Reply

Marsh Posté le 27-10-2004 à 12:57:15    

sans déconner ...
 
man setsockopt + SO_REUSEADDR

Reply

Marsh Posté le 27-10-2004 à 12:58:58    

ah j'imagine que le SO_REUSEADDR permet de réutiliser l'adresse... hum hum

Reply

Marsh Posté le 27-10-2004 à 13:00:49    

lol dsl si ca parait pas évident pour moi mais mon man il me parle pas de so_reuseaddr... enfin maintenant que j'ai tilté...

Reply

Marsh Posté le 27-10-2004 à 13:18:25    

bon j'ai intégré set sockopt. ca marche toujours qu'une seule fois apres delog et relog. je sais pas ce que j'ai mal fait.
 
si tu as le temps de mater un peu le code (regarde au niveau du bind) merci beaucoup
___________________________________________________________
 
 
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>   // Gestion Fichier  
#include <malloc.h>   // Fonctions mémoire
#include <stdlib.h>   // Fonctions mémoire
 
// ---------------- DECLARATION FONCTIONS
void Serveur(void);   // Le Serveur
void Erreur(char *);  // Erreur Fatale au Serveur
 
// ---------------- CONSTANTES + VARIABLES GLOBALES  
#define FICHIER  "source.txt" // Fichier Source
#define FICH_MAX_SIZE 10000 // Taille Maximum de Fichier  
#define PORT_SERVEUR 4000  // Numéro Port du Socket Serveur (1 à 65535)
 
int sock;     // La Socket
struct sockaddr_in sinfo;    // Infos sur la Socket
int sinfosize;     // Taille structure sinfo
FILE *fich;      // Pointeur fichier Source
void *on;
 
// *********
// main
// *********
int main()
{
 
 while(1) Serveur(); // Lancement du Serveur Jamais d'arrêt du Serveur
 return 0;   //fin du programme (jamais atteind !)
}
 
 
 
// *********
// Serveur  
// *********
void Serveur(void)
{
 int Etat;    // Retour des commandes Socket
 int ServeurON;   // false => Fin Serveur , true => Serveur en route
 char *buffer;   // buffer memoire, va contenir le fichier
 int TailleFichier;  // Taille Fichier
 
 
// __________________________ CREATION SOCKET __________________________________________
 
 
 sock=socket(AF_INET,SOCK_STREAM,0);  // Tentative Creation Socket
 if (sock==-1)
 {
 fprintf(stderr,"-------------ERREUR------------ Creation Socket Impossible !\n" );  
 exit(0);
 }
 
 fprintf(stderr,"Socket crée ! --------- OK\n" );
 
 sinfo.sin_addr.s_addr = htonl(INADDR_ANY);  // @IP Socket = @IP Ordinateur
 sinfo.sin_family = AF_INET;    // Protocole internet  
 sinfo.sin_port = htons(PORT_SERVEUR); // Port du Socket Serveur
 
 setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)); // pour réutiliser l'adresse pour un bind ulterieur
 
 
// ________________________________ BIND _______________________________________________
 
 
 Etat=bind(sock,(struct sockaddr *)&sinfo,sizeof(sinfo)); // Attache Socket  
 if (Etat==-1)
 {
 fprintf(stderr,"-----------ERREUR---------- Socket: Bind Impossible !\n" );  
 perror(bind);
 close(sock);
 exit(0);
 }
 
 fprintf(stderr,"Bind réussi ! -------- OK\n" );
 
// _____________________________ LISTEN ________________________________________________
 
 
 Etat=listen(sock,0);     // Mise en écoute Socket
 if (Etat<0)
 {
 fprintf(stderr,"----------ERREUR----------- Socket: Ecoute Impossible !\n" );  
 close(sock);
 exit(0);
 }
 
 fprintf(stderr,"Mise en écoute ------- OK\n" );
 
 ServeurON=1;       // Le Serveur à démarré
 
 fprintf(stderr,"ServeurON mis à %d\n",ServeurON);
 
 
// _______________________ RESERVATION BUFFER MEMOIRE __________________________________
 
 if ((buffer=(char *)malloc(FICH_MAX_SIZE))==NULL)
 {
 fprintf(stderr,"-----------ERREUR------------ Reservation Memoire Impossible !\n" );  
 close(sock);
 exit(0);
 }
 
 fprintf(stderr,"Réservation mémoire -------- OK\n" );
 
 
// ______________________________________  BOUCLE SERVEUR _________________________________________________
 
 
 while(ServeurON==1)     // Boucle permanente tant que ServeurON=true
 {
  sinfosize = sizeof(sinfo);   // Taille Structure sinfo
   
// _____________________________ ACCEPT
 
  if((sock=accept(sock,(struct sockaddr *)&sinfo,&sinfosize))!= -1)
  {  
   // OK LE SERVEUR A ACCEPTE LA CONNECTION CLIENT
   fprintf(stderr,"CONNEXION ETABLIE ----------- OK\n" );
 
// ____________________________ FICHIER
 
   if ((fich=fopen(FICHIER,"rb" ))==NULL)
   {
   fprintf(stderr,"----------ERREUR------- Ouverture Fichier Impossible !\n" );
   close(sock);
   exit(0);
   }
   fprintf(stderr,"Fichier %s ouvert ----------- OK\n",FICHIER);
   
   TailleFichier=fread(buffer,1,FICH_MAX_SIZE,fich); // Lecture dans FICHIER
   fprintf(stderr,"TailleFichier = %d\n",TailleFichier);
   
// ____________________________ SEND
 
   if (send(sock,buffer,TailleFichier,0)<0)
   {
   fprintf(stderr,"----------ERREUR-------- Erreur send transmission du Serveur !\n" );
   close(sock);
   exit(0);
   }
   fprintf(stderr,"SEND ------------ OK\n" );
 
   
// ___________________________ CLOSE
 
   fclose(fich); // Fermeture Fichier
   ServeurON=-1;
   fprintf(stderr,"ServeurON = %d\n",ServeurON);
 
   
  } else { fprintf(stderr,"--------ERREUR------- CONNEXION BAAAD, ACCEPT FOIREUX !!!\n" ); }
 }
 
// ________________________________________ FIN BOUCLE SERVEUR _________________________________________
 
 
 free(buffer);    // Libère mémoire
 sleep(1000);    // 1 secs d'attente => le client se deconnecte avant
 close(sock);   // Fermeture Socket
 fprintf(stderr,"-------- FIN SERVEUR ---------" );
}

Reply

Marsh Posté le 27-10-2004 à 13:20:27    

mais pourquoi tu fais 36 bind bordel, 36 sockets ...
 
 
ta boucle principal, ça doit être ton accept !

Reply

Marsh Posté le 27-10-2004 à 13:20:27   

Reply

Marsh Posté le 27-10-2004 à 13:32:31    

ah d'accord, je pense que je comprenais mal l'utilisation du socket. je pensais qu'a chaque envoi correspondait un nouveau socket puis une fois fini sa destruction...
donc le socket est toujours ouvert ? ca ne pose pas de pb de sécurité ?
mais mon code pourrait marcher si on fermait bien le socket, l'addresse etc en fin de boucle du serveur, non ?
 
mais si je fais comme tu dis, il faut forcément le listen dans la boucle (avant le accept)!
 
ou alors j'ai vraiment pas saisi le concept...
merci de m'éclairer niveau sens, et désolé de te prendre la tete mais jsuis encore très novice et je lutte pas mal (tout le monde y passe non ?) ;-)

Reply

Marsh Posté le 27-10-2004 à 13:34:33    

t'as vraiment rien compris entre socket public et socket privé ...

Reply

Marsh Posté le 27-10-2004 à 13:59:51    

wouaw, c'est constructif comme réponse :-D
si j'avais tout compris jserais pas la !
toi par contre, t'y es et t'as tout compris, j'imagine donc qu'aider les autres c'est une passion pour toi. Je te remercie d'ailleurs de bien vouloir répondre à mes problèmes (t'es le seul pour le moment, après tout), mais ton arrogance et ta fierté de programmeur expert né tout le monde s'en passerait bien. Contrairement à ton humilité.
 
merci quand meme... :-(

Reply

Marsh Posté le 27-10-2004 à 14:12:41    

Taz, si t'excite autant les filles que les nouveaux sur le forum, tu dois être un homme comblé...
 
Sinon Piper, il faut toujours garder ta socket d'écoute ouverte, et oui, ça pose des problèmes de sécurité (à toi de vérifier que ceux qui se connectent à ta socket le font proprement).  
 
Donc, la fonction "accept" te renvoie une socket d'échange. Mets la dans une autre variable que "sock" (qui est ta socket d'écoute), et c'est cette socket d'échange qu'il te faut fermer dans ta boucle.
 

Reply

Marsh Posté le 27-10-2004 à 14:15:11    

aaah merci beaucoup Lam's, c'est tout de suite plus clair, je vais essayer ca :-)

Reply

Marsh Posté le 27-10-2004 à 15:50:55    

merci beaucoup Lam's, ca fonctionne nikel !!
je comprends mieux le concept maintenant.
 
Reste a intégrer les différentes commandes sur le meme principe...
:-D

Reply

Sujets relatifs:

Leave a Replay

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