ssmint
Messages postés43Date d'inscriptionmercredi 30 novembre 2005StatutMembreDernière intervention 5 décembre 2008
-
9 août 2006 à 23:46
ZapaN28
Messages postés1Date d'inscriptionmercredi 8 février 2006StatutMembreDernière intervention 9 septembre 2010
-
9 sept. 2010 à 15:05
Bonjour à tous,
nouveau problème de socket, côté server cette fois ci :
imaginons que plusieurs clients cherchent à se connecter sur le port d'écoute du server en même temps,
je voudrais pouvoir recevoir toutes les connections puis choisir celle avec laquelle dialoguer...
=>Je fais donc un tableau de sock[] avec une boucle stoquant dans chaque sock les infos necessaires grâce à la fonction accept(), le problème, c'est que le socket server étant bloquant par défaut, la fonction accept() aussi..
Ce qui fait que la boucle bloque si il n'y a pas assez de conection entrantes. Dans mon code, j'ai pris 5 connections max mais s'il n'y en a que 2 ça ne marchepas , la boucle bloque sur la fonction accept()!!
=> Du coup, pas de problème : je rend donc le socket non bloquant grâce à la fonction ioctlsocket()!!
=> Sauf que du coup j'ai un autre problème lors de la communication avec le client, la fonction recv() n'est pas bloquante!
Alors c'est franchement chiant pour dialoguer, il faut mettre la fonction recv() dans une boucle infini pour recevoir un truc, compte tenu ds fonctionnalités que je veux mettre dans le prog, c'est impossible...
J'aimerais donc savoir si c'est possible de mettre une sorte de timeout sur la fonction accept() avec un socket bloquant ou "rerendre" le socket bloquant après avoir choisi le client (se que j'ai essayé mais qui ne marche pas)...
int main()
{
// variables
WSADATA wsa;
SOCKET server; //Le socket qui servira à écouter sur un port
SOCKET sock[5]; //les sockets qui serviront à communiquer
SOCKADDR_IN sinserv; //parametres pour server
SOCKADDR_IN sin[5]; //parametres pour socks
char buffer[50], *P, *ip;
int sinsize;
int i=0, c,tmp;
// Présentation :
system("color a");
system("cls");
system("TITLE TCP server by ssmint");
server = socket(AF_INET,SOCK_STREAM,0);
bind(server,(SOCKADDR*)&sinserv,sizeof(sinserv));
listen(server,5);
// Socket rendu non bloquant :
u_long p=1;
ioctlsocket(server, FIONBIO,&p);
// Affichage connections et choix :
printf("\nEcoute sur le port 1234. ..\t (3 sec)\n\n");
Sleep(3000);//necessaire pour mettre connection en queue
printf("Connexions recues :\t(5 max)\n");
memset(buffer,sizeof(buffer),0);
p=0; // NE FONCTIONNE PAS!!!
ioctlsocket(server, FIONBIO,&p); //une fois la fonction accept() passé
//le socket server reste non-bloquant
system("pause");
}
nightlord666
Messages postés746Date d'inscriptionvendredi 17 juin 2005StatutMembreDernière intervention23 mai 200710 10 août 2006 à 06:41
Pour ça, tu met ta boucle infinie avec recv dans un thread que tu aura créé. Regarde sur developpez.com, il y a un article sur les serveurs multithreads.
Sachant qu'on peut toujours enlever une ligne à un programme, et que dans un programme il y a toujours un bug, un programme peut se résumer à une ligne avec un bug.
turnerom
Messages postés492Date d'inscriptionsamedi 10 juillet 2004StatutMembreDernière intervention12 janvier 20121 10 août 2006 à 09:52
Re,
il faut que tu utilise la fonction select, voici un exemple de code qui marche (version Linux par contre mais l'idée est la, c'est + ou - la meme chose sous WinWin)
Ce code permet a nombre illimité (enfin presque 64511 pour etre precis) de client de se connecter, et lui envoi le fichier passer en paramètre.
int
main
(
int argc, char*argv[])
{
intds,port,ta,da,sock;
structsockaddr_inname;
if(argc!= 2)/* Test Le nombre d'arguments */
{
fprintf(stderr,"Usage : ./serveur port \n");
exit(0);
}
puts("Serveur en attente");/*Message d'attente*/
puts("");
port =atoi(argv[1]);/*L'argument 1 est le numero de port sur lequel le serveur attend*/
ds= socket(PF_INET, SOCK_STREAM, 0);/*On crée notre socket de connection*/
if (ds<0)/*Avec un test pour éviter les erreurs*/
{ perror("Probleme socket : ");
exit(-1);
}
init_sockaddr(&name,"0.0.0.0",port);/*On initialise notre socket internet, le port ecoute sur toute les adresse*/
if(bind(ds, (structsockaddr*)&name, sizeof(structsockaddr))<0)/*On bind*/
{/*Avec un test pour éviter les erreurs*/
perror("Probleme bind : ");
exit(-1);
}
if(listen(ds, FILED)<0)/*On listen dans notre socket de connexion jusqu'à "FILED" client max*/
{/*Avec un test pour éviter les erreurs*/
perror("Probleme listen ");
exit(-2);
}
while(1)/*Serveur multi-client donc boucle infinie*/
{
FD_ZERO(listeClients);/*On reinitialise notre liste d'attente*/
FD_SET(ds,listeClients);/*Dans laquelle on place notre socket de connexion*/
if((select(FILED+1, listeClients, NULL, NULL,NULL))<0)/*On fait notre select sur notre liste de client*/
{/*Avec un test pour éviter les erreurs*/
perror("select");
exit(-3);
}
for(sock =3;sock<FILED;sock++)/*On parcourt toutes nos (potentielles) sockets*/
{
if(FD_ISSET(sock,listeClients))/*On regarde quelle descripteur change d'etat*/
{ if(sock= =ds)/*Si c'est la socket de connection...*/
{
da =accept(ds, (structsockaddr*)&name, &ta);/*...on l'accepte...*/
if(da<0)/*...toujours avec un test pour éviter les erreurs...*/
{ perror("Probleme accept ");
exit(-3);
} printf("Connexion socket n°%d établie\n",da);
FD_SET(da,listeClients);/*...et on la rajoute dans notre liste de clients*/
} elsetraiterClient(sock);/*Si ce n'est pas la socket de connection, c'est alors une socket de data*/
/*On appelle donc notre fonction de transfert proprement dite en passant en argument...*/
}/*...la socket où le client envoi son fichier*/
}
name->sin_family= AF_INET;/* Adresses IPV4 (Internet) */
name->sin_port=htons(port);/* On gère le little/big Endian */
hostinfo=gethostbyname(hostname);/* appeler les fonctions de résolution de nom de la libC */
if (hostinfo == NULL)/* Si ne peut transformer le nom de la machine en adresse IP */
{
fprintf(stderr, "Unknown host %s.\n", hostname);
exit(-1);
} name->sin_addr =*(structin_addr*)hostinfo->h_addr;/* Le dernier champs de la structure est garni */
}
if(read(da,nomFich,SIZE)<0)/*On récupere le nom du fichier*/
{/*Avec toujours un petit test pour éviter les erreurs*/
perror("Nom de fichier non recu : ");
exit(-4);
}
if(nomFich= =NULL)/*Avec meme un 2eme test pour être totalement sûr*/
{
perror("Nom de fichier invalide");
exit(-5);
}
/*Si tout es bon...*/
fich =open(nomFich,O_WRONLY|O_CREAT,777/*,S_IRWXU|S_IRWXG|S_IRWXO*/);/*On ouvre le fichier (ou on le cree s'il n'existe pas) en lecture seule avec le nom recu*/
/* voir (1) en bas de page*/
puts("Réception en cours...");
while((size=read(da,buffer,SIZE)))write(fich,buffer,size);/*Tant que c'est pas la fin du fichier on lit dans la socket et on ecrit dans le fichier*/
puts("Réception terminée");
puts("");
close(da);/*On ferme la socket...*/
close(fich);/*...et le fichier*/