Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
3306 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [C] poll() & sockets

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C] poll() & sockets

n°1328558
Dinan
Posté le 20-03-2006 à 00:21:54  profilanswer
 

Bonjour,
 
Je cherche à coder un serveur multi-clients et utiliser poll() pour la gestion des sockets.
 
J'ai fait quelque teste.
 

Code :
  1. if ((new_fd = accept(s_listen, (struct sockaddr *)&their_addr, (unsigned int *)&sin_size)) > 0) {
  2.   old_flags = fcntl(new_fd, F_GETFL, 0);  // On récupère l'ancien bitmask
  3.   fcntl(new_fd, F_SETFL, old_flags | O_NONBLOCK); // Et on lui ajoute le non bloquant = SOCKET non Bloquant
  4.   poll_list[0].fd = new_fd;
  5.   poll_list[0].events = POLLIN | POLLPRI;
  6.   while (1) {
  7.    poll(poll_list, 2, -1);
  8.    //printf("Entering...\n" );
  9.    if (poll_list[0].revents & (POLLIN)) {
  10.      printf("recu\n" );
  11.    }
  12.   }


 
Donc voilà, avec des sockets non bloquant.
 
Mais j'ai quelque problèmes :
- Y'a t'il un autre moyen qu'en whilant ou de verifier dans le while si il y'a eu un event au lieu de while(1).
- Pourquoi les flags de revents ne se mettent pas à jour à chaque boucle (si je recois une donnée, dans toutes les boucles suivante mon file descriptor aura le flag POLLIN.
 
Merci :)

mood
Publicité
Posté le 20-03-2006 à 00:21:54  profilanswer
 

n°1328595
nargy
Posté le 20-03-2006 à 02:20:37  profilanswer
 

Est ce que tu as pensé à utiliser des thread ou des processus?

n°1328598
nargy
Posté le 20-03-2006 à 02:44:22  profilanswer
 

D habitude on utilise plutôt la fonction accept() sur un socket serveur bloquant. (voir man 2 accept, man 2 listen).
Puis quand une connection arrive, on crée une nouvelle thread ou un nouveau processu pour traiter la connexion.
 
poll() est plutôt utilisé sur plusieurs sockets à la fois. Là tu n en a qu une, et pourtant tu fait:
  poll(poll_list, 2, -1);
en est tu sur?
 
Dans ton code la ligne ...accept(listen(...))) n accepte qu une seule connexion client. Tu devrai mettre le listen avant et boucler sur accept. le poll() porte ici sur la socket client.

n°1328607
Dinan
Posté le 20-03-2006 à 08:24:45  profilanswer
 

J'ai juste montrer un exemple, mon serveur est censé accepter 2000 connection et mon listen se situe avant.
 
Je ne vais pas créer un thread pour 2000 connection :)

n°1328613
Emmanuel D​elahaye
C is a sharp tool
Posté le 20-03-2006 à 09:01:04  profilanswer
 

Dinan a écrit :

J'ai juste montrer un exemple, mon serveur est censé accepter 2000 connection et mon listen se situe avant.
 
Je ne vais pas créer un thread pour 2000 connection :)


Evidemment non, mais il est courant de créer un thread par connexion. C'est fait pour. Il faut de la mémoire, c'est tout.


Message édité par Emmanuel Delahaye le 20-03-2006 à 09:01:53

---------------
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/
n°1328658
Taz
bisounours-codeur
Posté le 20-03-2006 à 10:27:58  profilanswer
 

et le retour de poll, tu t'en fiches ?

n°1329192
Dinan
Posté le 20-03-2006 à 23:41:41  profilanswer
 

Code :
  1. while (1) {
  2.    verif = poll(poll_list, 1, 5000);
  3.    if (verif == 0 || verif == -1) {
  4.     continue;
  5.    }
  6.    //printf("Entering...\n" );
  7.    if (poll_list[0].revents & (POLLIN)) {
  8.      printf("recu\n" );
  9.    }
  10.   }


 
Meme résultat :(((
 
Et pour les thread, je me suis renseigné apparement pour bcp de connection c'est trop lourd (mon serveur est sensez pouvoir recevoir 2000 connection mais par seconde, meme avec un pool thread serait trop lourd.
 
Mais bref ! j'ai toujour problème avec poll().
 
Quelqu'un aurait un tuto avec exemple mise à part le man ?
 
Merci :)

n°1329194
Taz
bisounours-codeur
Posté le 20-03-2006 à 23:47:18  profilanswer
 

si c'est -1, c'est sans doute une erreur, pas un cas à ignoré. voir perror()
 
c'est fait exprès les poll et le non-bloquant ? tu t'emmêles pas les pinceaux là ?  
 
et c'est quoi le problème en fait ? si ça reste sur POLLIN, c'est que y a des données, voilà tout, rien de sorcier ...

n°1329203
nargy
Posté le 21-03-2006 à 00:31:25  profilanswer
 

Quitte à me répéter:
 
> Dans ton code la ligne ...accept(listen(...))) n accepte qu UNE seule connexion client.
 
> le poll() porte ici sur la socket CLIENT.
 

Code :
  1. // on boucle sur la socket client
  2.     while (1) {
  3. // on attends un évènement sur la socket client
  4.                     verif = poll(poll_list, 1, 5000);
  5.                     if (verif == 0 || verif == -1) {
  6. // on continue tranquillement même en cas d erreure
  7.                         continue;
  8.                     }
  9.                     //printf("Entering...\n" );
  10. // on a reçu un évènement sur la socket client
  11.                     if (poll_list[0].revents & (POLLIN)) {
  12. // l évènement est: donnée reçue
  13.                             printf("recu\n" );
  14. // on ne lit pas la donnée reçue, comme ça on peut continuer de boucler indéfiniment sur le même évènement
  15.                     }
  16.                  }


n°1329225
Dinan
Posté le 21-03-2006 à 08:17:07  profilanswer
 

Taz -> Non il n'ya aucune donnée.
nargy -> Je connect 1 seul socket en effet mais c'est pour faire mes teste, j'ai tester avec une 20 aine de connection c'est pareil

mood
Publicité
Posté le 21-03-2006 à 08:17:07  profilanswer
 

n°1329226
Dinan
Posté le 21-03-2006 à 08:21:20  profilanswer
 

Je crois en faite que vous n'avez pas compris mon problème :
 
Pourquoi cela while a l'infinie sur "recu" dès que j'envoi 1 octect !

n°1329242
franceso
Posté le 21-03-2006 à 09:09:35  profilanswer
 

tant que tu ne lis pas les données que tu as reçues, elles sont toujours disponibles et poll continue à te générer un événement POLLIN

n°1329644
Dinan
Posté le 21-03-2006 à 16:56:51  profilanswer
 

merci beaucoup franceso, je n'y avait pas pensé :)

n°1329812
Dinan
Posté le 21-03-2006 à 22:15:09  profilanswer
 

Pour savoir,
 
Normalement le flag POLLHUP ou POLLERR est sensé s'ajouter au bitmask quand le client se déco ?
 
Car moi pas du tout Oo
 
Merci

n°1329816
Taz
bisounours-codeur
Posté le 21-03-2006 à 22:24:06  profilanswer
 

et pourtant ...
 
ça peut varier en fonction de l'OS. si t'as un POLLIN de toutes façons, tu fais ton read, si ça te retourne 0, ben c'est EOF.


Message édité par Taz le 21-03-2006 à 22:25:44
n°1329827
Dinan
Posté le 21-03-2006 à 22:31:24  profilanswer
 

Oui je sait bien pour le read mais j'aurait autant aimer exploiter a fond poll.
Pour info je suis sous Debian.
 
Enfin merci ^^

n°1329860
Dinan
Posté le 21-03-2006 à 23:30:46  profilanswer
 

Code :
  1. maxfd++;
  2.   old_flags = fcntl(new_fd, F_GETFL, 0);  // On récupère l'ancien bitmask
  3.   fcntl(new_fd, F_SETFL, old_flags | O_NONBLOCK); // Et on lui ajoute le non bloquant = SOCKET non Bloquant
  4.   poll_list[maxfd].fd = new_fd;
  5.   poll_list[maxfd].events = POLLIN | POLLPRI;
  6.   while (1) {
  7.    verif = poll(poll_list, maxfd, -1);
  8.    if (verif < 0) {
  9.     continue;
  10.    }
  11.    for (i = 1; i <= maxfd; i++) {
  12.     if (poll_list[i].fd == -1) {
  13.      continue;
  14.     }
  15.     //printf("Entering...\n" );
  16.     if (poll_list[i].revents & (POLLERR | POLLHUP)) {
  17.      printf("ended\n" );
  18.      break;
  19.     }
  20.     if (poll_list[i].revents & (POLLIN)) {
  21.       printf("recu %i\n", i);
  22.       if (recv(poll_list[i].fd, pSock, 512, 0) < 1) {
  23.        poll_list[i].fd = -1;
  24.       }
  25.     }
  26.    }
  27.   }


 
Etant donné que mon sock est non bloquant, comment eviter la charge maximum du CPU ?
 
Merci :)

n°1329879
nargy
Posté le 22-03-2006 à 00:05:31  profilanswer
 
n°1330055
Taz
bisounours-codeur
Posté le 22-03-2006 à 11:27:54  profilanswer
 

#for (i = 1; i <= maxfd; i++)
 
tu zappe le premier élément et overflow. on fait pas du pascal.
 
# poll(poll_list, maxfd, -1);
avec ça meme avec overflow, tu peux être sur que ton new_fd ne sera jamais traité
 
#if (poll_list[i].fd == -1)
 
je pense qu'avec ça, poll va te renvoyer -1
 
#if (poll_list[i].revents & (POLLERR | POLLHUP) {
# printf("ended\n" );
tu n'écoutes rien. je t'ai dit que s'il y a EOF, tu auras POLLIN
 
#if (recv(poll_list[i].fd, pSock, 512, 0) < 1)  
-1 ou 0 ça fait une sacrée différence.
 
# poll_list[i].fd = -1;
vire plutot ce descripteur de la liste

n°1330056
Taz
bisounours-codeur
Posté le 22-03-2006 à 11:28:32  profilanswer
 

Dinan a écrit :

Code :
  1. verif = poll(poll_list, maxfd, -1);


 
Etant donné que mon sock est non bloquant, comment eviter la charge maximum du CPU ?
 
Merci :)


lire le man de poll


Message édité par Taz le 22-03-2006 à 11:29:20
n°1330059
Taz
bisounours-codeur
Posté le 22-03-2006 à 11:30:15  profilanswer
 


jamais. c'est stupide, c'est juste la meilleure façon de s'assurer que son application va tourner le plus lentement possible.

n°1330751
Dinan
Posté le 23-03-2006 à 08:18:06  profilanswer
 

Taz ma question n'était que sur la charge du CPU, pas sur le reste (le reste n'est pas un code que je vait utiliser, je met des bouts de code pour tester différentes solutions.) enfin merci quand meme et nargy j'ai jamais vu qu'on ralentissait une application pour moins de charge.

n°1330808
nargy
Posté le 23-03-2006 à 10:17:15  profilanswer
 

usleep(0)
Ça fait pas aller le processus le plus lentement possible, ça oblige l OS à changer changer de contexte quand tu n a plus rien à faire dans ta boucle while(1), et c est tout.
S il ne revient pas de usleep(0), c est qu il y a un autre processus fou qui fait un while(1).

n°1330812
nargy
Posté le 23-03-2006 à 10:21:29  profilanswer
 

> jamais. c'est stupide, c'est juste la meilleure façon de s'assurer que son application va tourner le plus lentement possible.
 
Quand tu n a rien à faire dans un while(1), la seule chose qui te reste à faire c est tourner le plus lentement possible.
C est pas parce que tu bouffe plus de CPU que les connexions vont arriver!

n°1330862
franceso
Posté le 23-03-2006 à 11:04:39  profilanswer
 

Citation :

usleep(0)
Ça fait pas aller le processus le plus lentement possible, ça oblige l OS à changer changer de contexte quand tu n a plus rien à faire dans ta boucle while(1), et c est tout.  
 
C est pas parce que tu bouffe plus de CPU que les connexions vont arriver!


certes, mais si tu fais un usleep(t), tu traiteras en moyenne tes connexions entrantes avec un retard de t/2.
Si tu fais un usleep(0), tu vas effectivement laisser la main aux autres processus, mais tu vas quand même bouffer toute la puissance restante du processeur.
 
poll() et select() sont justement faits pour éviter ce genre de désagréments et placer ton processus en attente jusqu'au moment où il a quelque chose à faire.

n°1330981
nargy
Posté le 23-03-2006 à 13:04:10  profilanswer
 

franceso> entièrement d accord
 
J ai récupéré le nombre maximum de processus que préconise le noyau linux 2.4: 4096 (getrlimit)
 
On est donc en dessous avec 2000. Le traitement par thread ou processus reste envisageable.
 
Au delà de cette valeur, il est préférable d avoir un load balancing.
 
Le choix final dépends de la taille des connexions traitées, ``4096`` correspondant sûrement à l ordre de grandeur du kilooctet.
 
Pour des mégaoctets ou des octets il faudrait des tests. C est à Dinan de voir.

n°1331250
Dinan
Posté le 23-03-2006 à 18:02:50  profilanswer
 

Non les thread pour mon projet n'est pas une solution étant donné que les connections par clients seront toute les 2sec environs. De toute facon je n'est aucunement donné un avis sur la facon dont je traiterait mes clients.
Poll reste la meilleur solution d'après nombre d'avis.
 
Enfin, merci, je vait chercher pour la charge de Poll.
 
Merci fransesco

n°1331498
franceso
Posté le 24-03-2006 à 10:09:17  profilanswer
 

Citation :

Non les thread pour mon projet n'est pas une solution étant donné que les connections par clients seront toute les 2sec environs.

c'est pas seulement ça qui est important ; c'est aussi le temps que tu mets pour servir un client. Si tes connexions arrivent toutes les deux secondes, mais que tu mets 10 minutes à traiter la demande d'un client, tu vas pas t'en sortir avec un seul thread/processus.
 

Citation :

Merci fransesco

De rien, mais c'est franceso

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [C] poll() & sockets

 

Sujets relatifs
Passer à travers un proxy avec les sockets.communication code php et C via sockets
Problème de sockets TCP[C] Problème de sockets
[Sockets]Problème étrange[wxWidgets] sockets et base de données
problème avec les sockets pour passer de windows a linux[C++]Encore des sockets...Pb: Bad Address
problème applet et socketsErreur flagrante? Serveur (sockets + threads)
Plus de sujets relatifs à : [C] poll() & sockets


Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)