Coucou c'est re-mouaaaaaa !
Bon, cette fois je fournis mon code source du serveur complet, pour que les puristes puissent faire "arrrghhhh", et que les autres puissent m'aider :-)
Alors déjà si quelqu'un a compris ce que je veux faire a la seule vue du code bravo !
Pour les autres, je tente une pseudo technique crado, pour tenter d'imiter une sorte de wall.
Le serveur ecoute sur un port, quand quelqu'un se pointe, il accepte la connexion. problème, j'arrive pas a le faire accepter sur un autre port que celui sur lequel il ecoute ! :-(
Résultat dès qu'un client se connecte, le serveur n'ecoute plus...
Si quelqu'un peut m'aider en pointant l'os dans le paté, ou meme en me corrigant 2-3 lignes de codes (pas tout hein, yaurai trop a faire pour que ce soit propre...puis jlaime bien mon style crados de pseudo codeur en herbe)
Bref,
merci d'avance.
P.S : oui je sais, le code est pourri, mal codé, et c'est débile de vouloir faire ca, mais si vous voulez pas m'aider, me criez pas dessus hein, allez donc lire un autre journal, yen a plein
- cho7, celui qui se fait souvent crié dessus, car il poste des journaux sans interet aucun, et qu'en plus il a pseudo totalement con -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define MAX_CONNECT 50
#define PORT 1983
int main(int argc, char * argv[])
{
int i;
int nb_connect=0; /* nombre de connexions en cours*/
int fds,nb_octets;
int fdc[MAX_CONNECT]; /* table contenant tous les file descriptor des clients */
int sin_size;
struct sockaddr_in serveur; /* les sockets */
struct sockaddr_in client[MAX_CONNECT];
char message[256]; /* on y stock les datas émisent par les différents clients */
/* on ouvre un socket */
if ((fds=socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf("Erreur, le socket serveur n'a pu etre créé !\n");
exit(1);
}
/* on initialise tout */
serveur.sin_family=AF_INET;
serveur.sin_port=htons(PORT);
serveur.sin_addr.s_addr=INADDR_ANY;
memset(&(serveur.sin_zero),'\0',8);
/* on bind le socket */
if (bind(fds,(struct sockaddr *)&serveur,sizeof(struct sockaddr)) == -1)
{
printf("Erreur, le bind n'a serveur n'a pu etre effectué !\n");
exit(1);
}
if (listen(fds,5) == -1)
{
printf("Erreur, la fonction listen coince !");
exit(1);
}
/* démarrage de la boucle evenementielle infinie */
while(1)
{
sin_size = sizeof(struct sockaddr_in);
if ((fdc[nb_connect]=accept(fds,(struct sockaddr *)&client[nb_connect],&sin_size)) == -1)
{
continue;
}
else
{
nb_connect++; /* hop, un client de plus */
}
for (i=0;i<nb_connect;i++)
{
/* on récupere pour chaque file descriptor les données qui veulent entrer sur le serveur */
if ((nb_octets=recv(fdc[i],message,256,0)) == -1)
{
message[nb_octets]='\0';
printf("%s\n",message);
}
}
for (i=0;i<nb_connect;i++)
{
/* on ferme tous les sockets client */
close(fdc[i]);
}
close(fds);
}
return 0;
}
# Re: Broadcast en C
Posté par shal . Évalué à 4.
Il faut alors forker (man fork)
le pere retourne attandre sur l'accpet
le fils discute avec le client..
A+
[^] # Re: Broadcast en C
Posté par mathieu mathieu (site web personnel) . Évalué à 3.
[^] # Re: Broadcast en C
Posté par LaBienPensanceMaTuer . Évalué à 1.
Sachant que pr accepter plusieurs connexions, tu dois créer un nouveau process qui pourra écrire dans cette variable il te faut un thread. En effet, un fork n'est rien d'autre qu'une copie mémoire du process s'executant. Toutes tes modifications au variables programme principal n'auront donc aucun effet pr les variables du programmes principal.
Donc deux solutions:
1/ Le thread (pthread_create())
2/ Garder un process unique et x sockets (select())
En espèrant avoir été suffisament compréhensible,
++, Gérald.
[^] # Re: Broadcast en C
Posté par gawal . Évalué à 2.
[^] # Re: Broadcast en C
Posté par cho7 . Évalué à 0.
Je débute en C, j'suis vraiment pas doué !
[^] # Re: Broadcast en C
Posté par gnumdk (site web personnel) . Évalué à 1.
# Re: Broadcast en C
Posté par thranduil . Évalué à 3.
[^] # Re: Broadcast en C
Posté par cho7 . Évalué à 1.
C'est pour ca que jvoulais tenter de faire accepter la connexion sur un nouveau port, quitte a en monopoliser 1000 si ya 1000 clients, car je pense que ce serait plus simple pour moi.
[^] # Re: Broadcast en C
Posté par Clément Stenac (site web personnel) . Évalué à 1.
Donc il faudra soit créer 1000 threads, chacun gérant une socket, soit faire un select.
Grosso modo, select, c'est, tu mets tous tes descripteurs de socket ( l'entier renvoyé par accept) dans un fd_set tu fais un select en spécifiant un timeout, et il te renvoie le fd_set avec dedans toutes les sockets sur lesquelles quelque chose est arrivé (c'est très simplifié comme explication)
Donc, grosso modo, en mettant que tu aies un tableau sockets contenant les descripteurs, et fd l'identifiant de ton fd_set:
fd_set fd;
struct timeval timeout;
/* On vide le fd_set
FD_ZERO( &fd );
/* On remplit le fd_set */
for( i = 0 ; i< taille_de_sockets ; i++)
{
FD_SET( sockets[i]; &fd );
}
/* Attendre 1seconde et demi */
timeout.tv_sec = 1;
timeout.tv_sec = 500000;
i_ret = select( taille_de_sockets, &fd, NULL, NULL, &timeout);
/* On regarde quelles sockets ont répondu et on traite */
if( i_ret == -1 && errno != EINTR)
{
/* Erreur */
}
else if (i_ret > 0)
{
/* Au moins une socket a renvoyé qqch (le nombre de sockets ayant renvoyé est i_ret) */
for (i = 0 ; i< taille_de_sockets ; i++)
{
if( FD_ISSET( sockets[i], &fd ) )
{
/* Des données sont arrivées sur cette socket */
process( sockets[i] );
/* On peut faire un recv sur cette socket pour récupérer les données*/
}
}
}
else if( i_ret == 0)
{
/* Aucune socket n'a recu de données avant l'expiration du timeout */
}
[^] # Re: Broadcast en C
Posté par cho7 . Évalué à 0.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define MAX_CONNECT 50
#define PORT 1983
int main(int argc, char * argv[])
{
int i;
int ret_val;
int nb_connect=0; /* nombre de connexions en cours*/
int nb_octets;
int fds; /* table contenant tous les file descriptor des clients */
int fdc[MAX_CONNECT];
int sin_size;
struct sockaddr_in serveur; /* les sockets */
struct sockaddr_in client;
fd_set fd;
struct timeval timeout;
char message[256]; /* on y stock les datas émisent par les différents clients */
/* on ouvre un socket */
if ((fds=socket(AF_INET,SOCK_STREAM,0))==-1)
{
printf("Erreur, le socket serveur n'a pu etre créé !\n");
exit(1);
}
/* on initialise tout */
serveur.sin_family=AF_INET;
serveur.sin_port=htons(PORT);
serveur.sin_addr.s_addr=INADDR_ANY;
memset(&(serveur.sin_zero),'\0',8);
/* on bind le socket */
if (bind(fds,(struct sockaddr *)&serveur,sizeof(struct sockaddr)) == -1)
{
printf("Erreur, le bind serveur n'a pu etre effectué !\n");
exit(1);
}
if (listen(fds,5) == -1)
{
printf("Erreur, la fonction listen coince !");
exit(1);
}
/* démarrage de la boucle evenementielle infinie */
while(1)
{
sin_size = sizeof(struct sockaddr_in);
timeout.tv_sec=1; /* rafraichissement du select = 1 seconde */
if ((fdc[nb_connect]=accept(fds,(struct sockaddr *)&client,&sin_size)) == -1)
{
continue;
}
else
{
printf("Connexion d'un nouveau client (file descriptor : %d) sur le port %d\n",fdc[nb_connect],(int)client.sin_port);
FD_SET(fdc[nb_connect],&fd); /* on ajoute le fd dans le select */
nb_connect++;
}
ret_val=select(nb_connect,&fd,NULL,NULL,&timeout);
if (ret_val>0) /* des données sont arrivées via un des sockets */
{
for (i=0;i<nb_connect;i++)
{
if(FD_ISSET(fdc[i],&fd))
{
/* on récupere pour chaque file descriptor les données qui veulent entrer sur le serveur */
if ((nb_octets=recv(fdc[i],message,256,0)) == -1)
{
message[nb_octets]='\0';
printf("%s\n",message);
}
} /* fin du FD_ISSET*/
} /* fin du for*/
}/* fin ret_val */
}
for (i=0;i<nb_connect;i++)
close(fdc[i]);
close(fds);
return 0;
}
[^] # Re: Broadcast en C
Posté par Clément Stenac (site web personnel) . Évalué à 1.
Ce que tu dois faire: dans le FD_SET, tu mets tous tes fdc et le fds.
Quand tu recois des données sur fds, alors tu fais un accept sur le fds pour récupérer le nouveau fdc et l'appel à acccept retournera tout de suite
# Re: Broadcast en C
Posté par xilun . Évalué à 1.
Gnnnnn ? C'est quoi cette idée de ouf ?
[^] # Re: Broadcast en C
Posté par shal . Évalué à 4.
alors soit gentil avec lui.
T'a plein de gens qui discute en même temps sur le port 80 d'un serveur web.
Comment le systéme fait pour retrouver le bon process a qui envoyer les données?
Il utilise le port src.
Donc en fait ca phrase est plutot : j'arrive pas a le accepter depuis un autre port source !
[^] # Re: Broadcast en C
Posté par cho7 . Évalué à 1.
Comme ca le port initial reste libre d'ecouter les nouvelles demandes de connexions.
en gros :
serveur : listening on port 1983...
client : request_connection on port 1983
serveur : accept_connection on port 0 (=1er port disponible)
client : connecting to port 0 (le port attribué précédemment)
serveur : listening on port 1983...
etc...
C'etait comme ca que le chat que j'avais fais en bts fonctionnait.
Car si je faisai un winsock.accept directement sur le port 1983, bah la connexion se faisait, mais les autres clients ne peuvent plus se connecter, car le port 1983 du serveur etait occupé !
Bref, j'ai ptetre rien compris, mais moi c'est le seul moyen que j'avais trouvé pour que ca marche.
[^] # Re: Broadcast en C
Posté par gnumdk (site web personnel) . Évalué à 1.
La solution la meilleur est accept().
Meme si le concept est un peu dure a comprendre au premier abord, ca marche tres bien :)
[^] # Re: Broadcast en C
Posté par xilun . Évalué à 1.
[^] # Re: Broadcast en C
Posté par Bilbo . Évalué à 1.
> Comme ca le port initial reste libre d'ecouter les nouvelles demandes de connexions.
Heeeuuuurrrkkkkk.... Le problème avec les programes comme celui que tu as developpé, c'est que tu ammenes ca dans une boite, on l'installe, et apres l'utilisateur va voir l'administrateur reseau/securité pour lui demander d'ouvrir des ports.
L'admin, generalement assez sympa, il demande (juste comme ça, en passant) : "Bon, il faut que je t'ouvre quels ports ? TCP/UDP ? vers où ? Y a un créneau horaire ?" (Oui, un admin c'est generalement assez parano...)
Et l'utilisateur du sus-dit logiciel qui répond, l'air de rien : "Bah en fait, il faudrait que tu m'ouvres tous les ports TCP > 1024, je ne sais quel port va utiliser mon serveur, c'est à la gueule du client..."
Et bein, moi, je t'assure que si c'est moi l'admin, ton programme, tu peux en changer tout de suite, sans passer par la case lecteur de CD-ROM...
# Re: Broadcast en C
Posté par Maillequeule . Évalué à 2.
http://linuxfr.org/~cho7kipu/10717.html(...)
M
[^] # Re: Broadcast en C
Posté par mouling . Évalué à 0.
[^] # Re: Broadcast en C
Posté par cho7 . Évalué à 0.
Ironie, quand tu nous tiens..
# Re: Broadcast en C
Posté par cho7 . Évalué à 1.
Après plusieurs heures acharnées, jpense avoir enfin compris le principe, j'ai utilisé select()
Merci a tous pour votre aide !
merci, merci, et merci !
[^] # Re: Broadcast en C
Posté par totof2000 . Évalué à 1.
# Commentaire supprimé
Posté par Anonyme . Évalué à 1.
Ce commentaire a été supprimé par l’équipe de modération.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.