Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: [Résolu][SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?  (Lu 4913 fois)

0 Membres et 1 Invité sur ce sujet

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Bonjour,

J'ai un socketSelector qui attend de cette manière :
selector.wait(sf::seconds(15)
Dès lors il retourne true si des sockets sont prêt et false au bout de 15 secondes si jamais aucun socket n'est prêt.

Mais j'ai commis l'erreur de faire :
socket.disconnect();
selector.remove(socket);

Dès lors je vais attendre 15 secondes sur la ligne du selector.wait qui va retourner false puis selector.wait retournera directement false sans attendre 15 secondes.
Il me semble évident que j'ai fait planter le socketSelector.

J'ai beau consulter la documentation, je n'ai pas trouvé le moyen de différencier si le false retourné par selector::wait est dû au timeout ou à une erreur.

Faut-il alors que je mette un sf::Clock pour repérer les erreurs ?
Existe-t-il d'autres moyen connu de faire planter le socketSelector? (pour savoir à quoi pourrait être dû l'erreur si jamais elle se reproduit).
« Modifié: Juillet 07, 2012, 08:29:30 pm par Neckara »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #1 le: Juillet 06, 2012, 07:19:13 pm »
Citer
Dès lors je vais attendre 15 secondes sur la ligne du selector.wait qui va retourner false puis selector.wait retournera directement false sans attendre 15 secondes.
J'ai pas compris. Tu peux la refaire en plus détaillée ? Peut-être montrer un code (un petit peu) plus complet au lieu de 1 + 2 lignes ?

Et n'hésite pas à utiliser le tag "code=cpp" au lieu de juste "code".
Laurent Gomila - SFML developer

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #2 le: Juillet 06, 2012, 08:01:04 pm »
sf::SocketSelector selector;
sf::TcpListener listener;
sf::TcpSocket socket;

listener.accept(&socket);
selector.add(socket);


socket.disconnect(); //provoque l'erreur
selector.remove(socket);

while(1)
{
         std::cout << selector.wait(sf::seconds(15))  << std::endl;
}
 
selector::wait va toujours retourner false directement quoi qu'il arrive sans attendre.

Si le socket.disconnect et le selector.remove sont appelé dans un autre thread pendant que le thread principal attend sur selector.wait, il attendra la fin des 15 secondes puis retournera false directement quoi qu'il arrive sans attendre.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #3 le: Juillet 06, 2012, 08:49:26 pm »
Et donc ? Qu'est-ce qui te pose problème dans tout ça ?
Laurent Gomila - SFML developer

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #4 le: Juillet 06, 2012, 08:58:23 pm »
J'aimerais savoir s'il existe un autre moyen de différencier si le return false est dû à la fin des 15 secondes ou s'il est dû à une erreur autre que de mettre un sf::Clock;

J'aimerais aussi savoir s'il est utile de mettre un sf::Clock ou s'il ne peut pas y avoir d'erreur dans SocketSelector::wait si on n'essaye pas de déconnecter soi-même les TcpSocket.


EDIT : j'ai compris l'erreur en regardant les sources.
Socket::disconnect() va mettre dans m_socket une valeur pour signifier que le socket est invalide.
Puis il fait appel à close() qui va fermer le socket proprement.
Mais SocketSelector.remove(socket) va lui aussi utiliser m_socket (via getHandle() ) pour l'enlever de la liste à écouter.
Comme je passe une valeur de socket invalide, il y a une erreur lors du FD_CLR d'où les returns false en boucle.

Il faut donc bien appeler socket.disconnect() mais après SocketSelector.remove() ?

J'ai relu la doc de TcpSocket, Socket et SocketSelector plusieurs fois mais je n'ai pas vu d'information à ce propos ce qui me semble assez dommage (à moins que je sois passé à côté).
« Modifié: Juillet 06, 2012, 09:45:23 pm par Neckara »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #5 le: Juillet 06, 2012, 10:50:11 pm »
Citer
J'aimerais savoir s'il existe un autre moyen de différencier si le return false est dû à la fin des 15 secondes ou s'il est dû à une erreur
False signifie que rien n'est prêt dans le sélecteur. Parfois il peut le savoir sans attendre les 15 secondes (si aucune socket valide n'est dedans), parfois pas. Mais au final tu as bien le résultat escompté. Dans quel but voudrais-tu avoir plus de détails ?

Citer
J'aimerais aussi savoir s'il est utile de mettre un sf::Clock ou s'il ne peut pas y avoir d'erreur dans SocketSelector::wait si on n'essaye pas de déconnecter soi-même les TcpSocket.
Ca paraît très philosophique tout ça. Quel est le problème concret que tu essayes de résoudre ?

Citer
Il faut donc bien appeler socket.disconnect() mais après SocketSelector.remove() ?
Oui en effet. Déconnecter une socket revient à l'invalider / la détruire. Après tu ne peux plus l'utiliser.

Citer
J'ai relu la doc de TcpSocket, Socket et SocketSelector plusieurs fois mais je n'ai pas vu d'information à ce propos ce qui me semble assez dommage (à moins que je sois passé à côté).
Faudra que je vérifie ça. Possible que je n'y avais pas songé avant d'écrire la doc :)
Laurent Gomila - SFML developer

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #6 le: Juillet 07, 2012, 09:43:40 am »
Je viens de comprendre.

Le problème vient du select (dans SocketSelector::wait ).

select retourne le nombre de socket près ou 0 si le timeout est expiré.

Donc return cout > 0; retournera true si des sockets sont prêt, false si le time out est expiré.

Sauf qu'il peut aussi retourner - 1 en cas d'erreur !

Trois erreurs pouvant se produire :
EBADF : Un descripteur de fichier (dans l'un des ensembles) est invalide.  (ce qu'il se passe avec moi)
EINTR : Un signal a été intercepté.
ENOMEM : Pas assez de mémoire pour le noyau.

Ne serait-il pas plus sage de d'enregistrer l'erreur si count = -1 et dans le cas où SocketSelector::wait() retourne false on puisse appeler une fonction .getErreur() qui retournera 0 si il n'y a pas d'erreur (timeout écoulé) et une erreur si une erreur c'est produite ?
« Modifié: Juillet 07, 2012, 09:48:21 am par Neckara »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #7 le: Juillet 07, 2012, 05:30:33 pm »
Dans quel cas de figure cela pourrait-il servir ?

C'est bien beau de gérer des trucs et des machins, mais encore faut-il que ce soit utile.
Laurent Gomila - SFML developer

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #8 le: Juillet 07, 2012, 06:42:04 pm »
Si je comprend bien, il est inutile de gérer ces erreurs car :

EBADF est dû au fait qu'on ai fait le TcpSocket::disconnect avant le SocketSelector::remove(). C'est donc une faute de l'utilisateur de la SFML.

EINTR est dû au fait qu'on ai réceptionne un signal. Mais comme les SocketSelector::remove() sont placés à l'intérieur d'une boucle, on va juste faire un tour de plus ?
Mais si on ne met qu'un seul TcpSocket dans le SocketSelector pour faire un timeout (comme conseillé dans la doc ou dans le tuto je sais plus), on va déconnecter le TcpSocket prématurément.
Ou alors si on décide que si on a pas de sockets prêt pendant 60 secondes, on déclenche une action particulière ?


ENOMEM est assez rare. Mais ne peut-il pas se produire ? Ne pourrait-on pas gérer cette erreur pour permettre au programmeur de décider quoi faire si jamais cette erreur se produit ?

Ne serait-il même pas plus efficace que SocketSelector::wait() retourne un int (count) et à l'utilisateur de faire le :
if(SocketSelector > 0) ;
Ce qui permettrait par la suite de gérer une éventuelle erreur ?


Non pas que je soit contrariant (bon un petit peu quand même), mais je suis assez curieux de nature et j'aimerais comprendre ce choix et peut être en apprendre quelque chose qui pourrait m'être utile dans mes propres programmes.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #9 le: Juillet 07, 2012, 08:06:51 pm »
Citer
Non pas que je soit contrariant (bon un petit peu quand même), mais je suis assez curieux de nature et j'aimerais comprendre ce choix
Flemme, simplicité et pragmatisme. Tant que je n'ai pas de bonne raison de faire une modif, je ne la fais pas. Honnêtement, je ne me pose pas autant de questions que toi, s'il n'y a pas d'utilisation concrète de tout ça côté utilisateur alors fin de l'histoire. Malheureusement je n'ai pas le temps de creuser moi-même, donc si personne ne me prouve le contraire je laisse tomber. Mais libre à toi de creuser de ton côté si tu le souhaites :)
Laurent Gomila - SFML developer

Neckara

  • Jr. Member
  • **
  • Messages: 77
    • Voir le profil
Re : Re : [SFML2.0]SocketSelector, comment savoir s'il y a une erreur ?
« Réponse #10 le: Juillet 07, 2012, 08:29:13 pm »
Flemme, simplicité et pragmatisme.
Les attributs d'un bon programmeur ;D
Il est vrai que si on doit toujours remettre en cause tout ce que l'on a codé et qu'on cherche à l'améliorer sans cesse, on ne progresse pas.

Le seul problème que je verrais, c'est l'utilisation du sf::SocketSelector avec un seul sf::TcpSocket dedans dans l'objectif d'avoir un timeout grâce à la méthode wait de sf::SocketSelector si jamais un signal est envoyé, on déconnecte le client à tort.


Merci d'avoir répondu à mes questions et toujours aussi rapidement.