Récupérer l'état d'une socket en sortie d'un select() - C++ - Programmation
Marsh Posté le 12-11-2005 à 11:21:39
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. |
Suffit de lire la doc de select()... Montre ton code...
Marsh Posté le 12-11-2005 à 11:34:17
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 :
|
Marsh Posté le 12-11-2005 à 12:52:15
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 ?
Marsh Posté le 12-11-2005 à 12:54:16
RTFM
$ man select
Marsh Posté le 12-11-2005 à 13:02:54
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 ?
Marsh Posté le 12-11-2005 à 13:05:01
a tout hasard, le code de retour ?
Marsh Posté le 12-11-2005 à 13:12:47
ReplyMarsh Posté le 12-11-2005 à 13:23:47
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.
Marsh Posté le 12-11-2005 à 13:30:51
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 |
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
Emmanuel Delahaye a écrit : Non. C'est un problème d'utilisation d'une fonction système. C'est indépendant du langage. |
ok
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
Marsh Posté le 12-11-2005 à 13:40:13
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...
Marsh Posté le 12-11-2005 à 13:48:40
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
Marsh Posté le 12-11-2005 à 14:41:44
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.
Marsh Posté le 12-11-2005 à 19:44:47
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
Marsh Posté le 12-11-2005 à 20:19:37
bah t'as un POLLIN, et quand tu tentes un recv, là tu constates que EOF
Marsh Posté le 12-11-2005 à 20:46:27
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
Marsh Posté le 12-11-2005 à 22:13:04
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
Marsh Posté le 12-11-2005 à 22:31:50
NUL ? regarde le retour de recv, si c'est 0, c'est EOF. man recv
Marsh Posté le 12-11-2005 à 23:05:58
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
Marsh Posté le 13-11-2005 à 00:12:44
n'hésite pas à consulter la VO du man
LC_ALL=C man poll
par exemple. Beaucoup de tradutions sont bugguées.
Marsh Posté le 13-11-2005 à 00:50:20
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...
Marsh Posté le 12-11-2005 à 11:02:10
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
NB : je développe sous linux, pas de fonctions windows, donc
Message édité par v10ware le 12-11-2005 à 12:50:30