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

  FORUM HardWare.fr
  Programmation
  C++

  Récupérer l'état d'une socket en sortie d'un select()

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Récupérer l'état d'une socket en sortie d'un select()

n°1244168
v10ware
Posté le 12-11-2005 à 11:02:10  profilanswer
 

Bonjour,
 
Je suis amené à gérer les connexions de plusieurs clients sur un serveur, en effectuant un select() sur ma socket serveur et l'ensemble des sockets déjà créées pour les clients.
J'aimerais savoir comment tester l'état des sockets sélectionnées par le select(), car cette fonction rend la main dès qu'une socket envoie des données ou se ferme côté client, sans que je sache pour l'instant distinguer les cas.
 
Merdi d'avance :jap:
 
NB : je développe sous linux, pas de fonctions windows, donc ;)

Message cité 1 fois
Message édité par v10ware le 12-11-2005 à 12:50:30
mood
Publicité
Posté le 12-11-2005 à 11:02:10  profilanswer
 

n°1244177
Emmanuel D​elahaye
C is a sharp tool
Posté le 12-11-2005 à 11:21:39  profilanswer
 

v10ware a écrit :

Je suis amené à gérer les connexions de plusieurs clients sur un serveur, en effectuant un select() sur ma socket serveur et l'ensemble des sockets déjà créées pour les clients.
J'aimerais savoir comment tester l'état des sockets sélectionnées par le select(), car cette fonction rend la main dès qu'une socket envoie des données ou se ferme côté client, sans que je sache pour l'instant distinguer les cas.


Suffit de lire la doc de select()... Montre ton code...


---------------
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°1244184
v10ware
Posté le 12-11-2005 à 11:34:17  profilanswer
 

Je passe tout simplement au select un fd_set avec les descripteurs de sockets dont je veux savoir si je peux y lire quelquechose.
 
Quand le client envoie des données, on quitte le select(), on lit les données et basta. Quand le client se déconnecte, on quitte également le select() comme si il y avait des données à lire sur la socket... J'aimerais savoir comment connaître l'état de la socket pour ne pas essayer de lire des données sur quelquechose de fermé.
 
Bon, mon code est en C++, mais j'ai choisi de le placer en C parceque c'est essentiellement un problème de fonctions C...
socketModify est une classe de manipulation de fd_set, Socket est une classe contenant le socket descriptor, les clés des maps sont les socket descriptors aussi...
 

Code :
  1. void SocketPool::select(map<int, Socket*> *mapSocket)
  2. {
  3.     if (mapSocket== NULL)
  4.     {
  5.         throw Exception(-1);
  6.     }
  7.     // construction du fd_set a passer au select()
  8.     socketModify.reset();
  9.     for (map<int, Socket*>::iterator it = pool.begin(); it != pool.end(); it++)
  10.     {
  11.         socketModify.add(it->first);
  12.     }
  13.     socketModify.add(ss.getDescriptor());
  14.     // select : le fd_set est modifie
  15.     int nbSockArrived = ::select(FD_SETSIZE, socketModify.getFd_Set(), NULL, NULL, NULL);
  16.    
  17.     if (nbSockArrived == -1)
  18.     {
  19.         // erreur du select
  20.         throw Exception(errno);
  21.     }
  22.    
  23.     if (nbSockArrived > 0)
  24.     {
  25.         for (map<int, Socket*>::iterator it = pool.begin(); it != pool.end(); it++)
  26.         {
  27.             // ajout des sockets actives a la liste
  28.             // il faudrait tester ici si la socket est active parcequ'elle a ete fermee par le client
  29.             // si c'etait le cas, il faudrait remplir une deuxieme liste indiquant a l'appelant
  30.             // quelles sont les sockets fermees
  31.             if (socketModify.isset(it->first))
  32.             {
  33.                 (*listSocket)[it->first] = it->second;
  34.             }
  35.         }
  36.         if (socketModify.isset(ss.getDescriptor()))
  37.         {
  38.             // la socket serveur a recu une nouvelle connexion
  39.             Socket *connec = new Socket(ss.accept());
  40.             pool[connec->getDescriptor()] = connec;
  41.         }
  42.     }
  43. }

n°1244222
v10ware
Posté le 12-11-2005 à 12:52:15  profilanswer
 

Voila... Même si je continue à croire que c'est un problème de fonctions qui ne regardent que le C, donc je voulais mieux cibler... Bref, on va pas épiloguer. Une idée ?

n°1244223
KangOl
Profil : pointeur
Posté le 12-11-2005 à 12:54:16  profilanswer
 

RTFM
 
$ man select
 


---------------
Nos estans firs di nosse pitite patreye...
n°1244226
v10ware
Posté le 12-11-2005 à 13:02:54  profilanswer
 

Tiens, j'y avais pas pensé :|
 
Tu veux bien le lire toi-même et me dire à quel endroit est indiquée la possibilité de savoir quel est l'état exact d'une socket en sortie du select ?


Message édité par v10ware le 12-11-2005 à 13:03:13
n°1244227
KangOl
Profil : pointeur
Posté le 12-11-2005 à 13:05:01  profilanswer
 

a tout hasard, le code de retour ?


---------------
Nos estans firs di nosse pitite patreye...
n°1244233
Taz
bisounours-codeur
Posté le 12-11-2005 à 13:12:47  profilanswer
 

moi je préfère poll/epoll :)
 
sinon man select_tut

n°1244237
Emmanuel D​elahaye
C is a sharp tool
Posté le 12-11-2005 à 13:23:47  profilanswer
 

v10ware a écrit :

Voila... Même si je continue à croire que c'est un problème de fonctions qui ne regardent que le C


Non. C'est un problème d'utilisation d'une fonction système. C'est indépendant du langage.


---------------
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°1244240
v10ware
Posté le 12-11-2005 à 13:30:51  profilanswer
 

KangOl a écrit :

a tout hasard, le code de retour ?


-1 : erreur
>= 0 : nombre de descripteurs selectionnés, qui figurent dans les fd_set modifiés par le select().
Pas d'information sur l'état des descripteurs, donc :/
 

Taz a écrit :

moi je préfère poll/epoll :)
 
sinon man select_tut


 
j'avais fait une recherche, j'ai trouvé un topic où tu parles de poll/epoll, je me suis un peu renseigné, il semble que ce soit quelquechose d'assez récent dont je ne sais pas si c'est disponible sur le système de développement de mon école (je suis sur un linux récent chez moi, mais là bas c'est un FreeBSD pas très frais...). Je regarderai quand même. Et je regarderai aussi select_tut :jap:
 

Emmanuel Delahaye a écrit :

Non. C'est un problème d'utilisation d'une fonction système. C'est indépendant du langage.


ok :jap:
 
 
Mais sinon, je pensais qu'il devait peut-être exister un appel système dont je n'aurais pas connaissance et qui permettrait de récupérer l'état d'un descripteur... Si vous avez des renseignements là dessus :)

mood
Publicité
Posté le 12-11-2005 à 13:30:51  profilanswer
 

n°1244243
Emmanuel D​elahaye
C is a sharp tool
Posté le 12-11-2005 à 13:40:13  profilanswer
 

v10ware a écrit :

Mais sinon, je pensais qu'il devait peut-être exister un appel système dont je n'aurais pas connaissance et qui permettrait de récupérer l'état d'un descripteur... Si vous avez des renseignements là dessus :)


 
FD_CLR / FD_ZERO / FD_SET permet de positionner le bit correspondant au socket à surveiller (en général on a un socket serveur, FILENO_STDIN et et c'est tout...). Ensuite, FD_ISSET permet de déterminer qui a bougé.
 
http://www.linux-france.org/articl [...] ect-2.html
 
Rappel :  
2 = fonction système
3 = fonction C...


---------------
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°1244244
v10ware
Posté le 12-11-2005 à 13:48:40  profilanswer
 

Je pense avoir bien saisi le fonctionnement des fd_set et les macros associées, donc j'arrive à les construire et les lire. Simplement, après lecture du fd_set retourné par select(), je ne sais pas déterminer la raison pour laquelle select() a retenu un descripteur particulier dans le fd_set retourné.
 
Comme j'ai dit, que la socket cliente ait envoyé des données ou qu'elle se soit déconnectée, elle figure dans le fd_set readfds, et là je ne sais pas comment me comporter.
 
Alors dans le cas où il s'agit d'arrivée de données, je sais qu'il faut que je lance un read() (ou peut etre un recv(), je viens de me souvenir de cette fonction peut être plus adaptée au cas des sockets), mais il serait bien que je ne tente pas de lire des données sur une socket fermée (après test ca me renvoie indéfiniment le même caractère ascii étendu 0xbf, et je ne pense pas que ce soit un critère suffisant pour déclarer la socket comment étant fermée, sauf si vous me confirmez le contraire).
 
sinon, merci pour le rappel sur la classification des pages man, j'ai jamais su exactement à quoi correspondaient les catégories :jap:

n°1244272
Taz
bisounours-codeur
Posté le 12-11-2005 à 14:41:44  profilanswer
 

select craint en terme de montée en charge et personnellement je ne trouve pas son API et ses fd_set pratiques. poll est mieux, plus performant et plus simple à utiliser à mon avis. Quant à epoll c'est vraiment génial, avec une sémantique beaucoup plus riche.

n°1244401
v10ware
Posté le 12-11-2005 à 19:44:47  profilanswer
 

Je viens de passer à poll, qui a le mérite d'indiquer la raison pour laquelle une socket est sélectionnée. Mais ce que je ne saisis pas bien, c'est que quand le client ferme sa socket, poll() détecte une activité sur la socket associée côté serveur (jusque là, comme select()) mais en indiquant que la raison est qu'il y a des données à lire (le champ "revents" contient POLLIN) et non que la socket est fermée (POLLHUP).
 
J'étais tout confiant et paf, l'enthousiasme retombe :/
Je vais quand même garder poll et virer select sur les conseils de Taz, mais ça ne résoud pas mon problème :/

n°1244407
Taz
bisounours-codeur
Posté le 12-11-2005 à 20:19:37  profilanswer
 

bah t'as un POLLIN, et quand tu tentes un recv, là tu constates que EOF

n°1244418
v10ware
Posté le 12-11-2005 à 20:46:27  profilanswer
 

Ce serait donc le caractère -65 que je reçois, EOF ?
Mais dans ce cas, à quoi correspond POLLHUP ?
 
Arf, en cherchant pendant que je rédige ma réponse, je tombe là dessus : http://www.greenend.org.uk/rjk/2001/06/poll.html
Il faudrait qu'ils se mettent d'accord :D


Message édité par v10ware le 12-11-2005 à 20:46:39
n°1244429
Taz
bisounours-codeur
Posté le 12-11-2005 à 21:03:54  profilanswer
 

EOF c'est EOF

n°1244469
v10ware
Posté le 12-11-2005 à 22:13:04  profilanswer
 

Bon, après plusieurs tests, il semblerait que ce ne soit pas EOF qui soit lu sur la socket, mais NUL. Je ne sais pas si c'est correct, mais ça marche ;)
 
Merci à tous, et merci pour poll :jap:

n°1244476
Taz
bisounours-codeur
Posté le 12-11-2005 à 22:31:50  profilanswer
 

NUL ? regarde le retour de recv, si c'est 0, c'est EOF. man recv

n°1244485
v10ware
Posté le 12-11-2005 à 23:05:58  profilanswer
 

Le retour de recv est bien 0, donc je lisais dans un buffer rempli de caractères NUL puisqu'initiliasé juste avant la lecture.
 
A ce sujet, les pages de man des serveurs de mon école ne mentionnent pas ce que signifie la valeur de retour 0 pour recv... Mais chez moi il est effectivement dit que cela signifie que la connexion est terminée.
 
Merci bien pour ton expertise, je vais pouvoir faire du code à peu près propre ;)

n°1244501
Taz
bisounours-codeur
Posté le 13-11-2005 à 00:12:44  profilanswer
 

n'hésite pas à consulter la VO du man
 
LC_ALL=C man poll
 
par exemple. Beaucoup de tradutions sont bugguées.

n°1244509
v10ware
Posté le 13-11-2005 à 00:50:20  profilanswer
 

Ce sont bien les pages anglaises que je consultais, mais le contenu dépend certainement des systèmes et/ou des versions des pages de man.
 
D'ailleurs, concernant recv, le man des serveurs de l'école n'indique rien concernant la valeur de retour 0, mais j'espère que la fonction se comporte de la même façon que chez moi...

mood
Publicité
Posté le   profilanswer
 


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

  Récupérer l'état d'une socket en sortie d'un select()

 

Sujets relatifs
avec insert/select es ce que je risque d'exploser le rollback segment?[VBA-EXCEL 2003] recuperer le nom de tous les feuilles dans une listbx
Récupérer Adresse IP Réseau [inet_ntoa]SELECT sur plusieurs tables à la fois
[bash] recuperer le resultat d'une commande SQL dans une variable bashRécuperer une varible Javascript en php dans un formulaire
SELECT DISTINCT dans un text et longtextRécupérer la taille d'un tableau associatif
Récupérer les valeurs boursières...recuperer une adresse mail
Plus de sujets relatifs à : Récupérer l'état d'une socket en sortie d'un select()


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR