Question

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
}

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. Cela me semble être un gaspillage de ressources que de devoir vider et remplir le jeu à chaque fois.

Quelqu'un a-t-il une bonne explication à cela, et même mieux, peut-être une suggestion pour l'éviter?

Était-ce utile?

La solution

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

Si vous craignez des frais généraux, le coût du traitement de FD_SET complet dans le noyau 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 noyau. Dans votre exemple:

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

Pour un cas plus complexe comportant 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 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 noyau 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 repasser continuellement.

Autres conseils

Lisez la page de manuel de sélection. 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.

Initialisez toujours le fd_set juste avant de l'utiliser.

C’est ainsi que fonctionne la sélection. 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 prises. Si vous voulez lire depuis un socket, il suffit de le lire ou de l’envoyer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top