comportement select () irritant dans c

while (xxx) { timeout.tv_sec=TIMEOUT; timeout.tv_usec=0; FD_ZERO(&set); FD_SET(sd,&set); switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout)) xxxxx } 

fonctionne bien, cependant

 FD_ZERO(&set); FD_SET(sd,&set); while (xxx) { timeout.tv_sec=TIMEOUT; timeout.tv_usec=0; switch (select(FD_SETSIZE,&set,NULL,NULL,&timeout)) xxxxx } 

ne pas Cela fonctionne la première fois, mais la prochaine fois qu’il parcourt la boucle while, il expire même si le socket sd reçoit des données. Il me semble que gaspiller des ressources est un gaspillage de ressources.

Tout le monde a une bonne explication pourquoi, et même mieux, peut-être une suggestion pour l’éviter?

    select modifie ses arguments. Vous devez vraiment le réinitialiser à chaque fois.

    Si vous êtes préoccupé par les coûts indirects, le coût du traitement de FD_SET complet dans le kernel est légèrement supérieur au coût de FD_ZERO. Vous voudriez ne transmettre que votre maximum fd, pas FD_SETSZIZE, pour minimiser le traitement du kernel. Dans votre exemple:

     switch (select((sd + 1),&set,NULL,NULL,&timeout)) 

    Pour un cas plus complexe avec plusieurs fds, vous devez généralement conserver une variable max:

     FD_SET(sd,&set); if (sd > max) max = sd; ... repeat many times... switch (select((max + 1),&set,NULL,NULL,&timeout)) 

    Si vous avez un grand nombre de descripteurs de fichier et que vous vous inquiétez de la surcharge liée à leur traitement, vous devriez examiner certaines des solutions de rechange permettant de sélectionner (). Vous ne mentionnez pas le système d’exploitation que vous utilisez, mais pour les systèmes d’exploitation de type Unix, il en existe quelques-uns:

    • pour Linux, epoll ()
    • pour FreeBSD / NetBSD / OpenBSD / MacOS X, kqueue ()
    • pour Solaris, / dev / poll

    Les API sont différentes, mais elles constituent toutes essentiellement une interface de kernel avec état permettant de gérer un ensemble de descriptions de fichiers actives. Une fois qu’un fd est ajouté à l’ensemble, vous serez averti des événements sur ce fd sans avoir à le retransmettre continuellement.

    Lisez la page de manuel select. L’ensemble renvoyé est constitué uniquement des descripteurs de fichier prêts à être utilisés. Vous êtes censé utiliser FD_ISSET pour vérifier chacun d’eux s’il est défini ou non.

    Toujours initialiser le fd_set juste avant de l’utiliser.

    C’est la façon dont fonctionne les travaux. Cela fonctionne mieux et a plus de sens si vous avez plus d’un socket. C’est un peu le problème: vous sélectionnez plusieurs sockets. Si vous voulez lire depuis un socket, lisez-le ou récupérez-le.