Reseau Socket - Problème de bind() dans un client/serveur local - C - Programmation
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
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 !!
Marsh Posté le 27-10-2004 à 12:31:04
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
man perror
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
Marsh Posté le 27-10-2004 à 12:58:58
ah j'imagine que le SO_REUSEADDR permet de réutiliser l'adresse... hum hum
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é...
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 ---------" );
}
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 !
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 ?) ;-)
Marsh Posté le 27-10-2004 à 13:34:33
t'as vraiment rien compris entre socket public et socket privé ...
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... :-(
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.
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 :-)
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
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 !