Pergunta

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
}

funciona bem, no entanto

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
}

não. Ele funciona da primeira vez, mas da próxima vez que atravessa o loop while fica um tempo limite, mesmo se a tomada de sd recebe dados. Parece-me ser um desperdício de recursos ter que esvaziar e encher definir cada vez.

Alguém tem uma boa explicação por que isso é, e ainda melhor, talvez uma sugestão como evitá-lo?

Foi útil?

Solução

selecione modifica seus argumentos. Você realmente tem que reinicializar-lo cada vez.

Se você está preocupado com a sobrecarga, o custo de processamento do fd_set completa no kernel é um pouco mais importante do que o custo de FD_ZERO. Você gostaria de passar apenas em sua fd máxima, não FD_SETSZIZE, para minimizar o processamento de kernel. No seu exemplo:

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

Para um caso mais complexo, com vários fds, você normalmente acaba mantendo uma variável máx:

FD_SET(sd,&set);
if (sd > max) max = sd;
... repeat many times...

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


Se você vai ter um grande número de descritores de arquivos e estão preocupados com a sobrecarga de schlepping-los sobre, você deve olhar para algumas das alternativas para selecionar (). Você não menciona o sistema operacional que você está usando, mas para Unix-like sistemas operacionais há alguns:

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

As APIs são diferentes, mas todos eles são essencialmente uma interface de kernel stateful para manter um conjunto de descrições de arquivos ativos. Uma vez que um fd é adicionado ao conjunto, você será notificado sobre os eventos nesse fd sem ter que continuamente passá-lo novamente.

Outras dicas

Leia a página man select. O conjunto retornado apenas os descritores de arquivos que estão prontos para ser usados. Você é suposto para usar FD_ISSET para verificar cada um, se ele é definido ou não.

Sempre inicializar o direito fd_set antes de usá-lo.

Essa é a maneira trabalhos seletos. Ele funciona melhor e faz mais sentido, se você tiver mais de um soquete. Isso é uma espécie de ponto: você está selecionando através de muitos sockets. Se você quiser ler a partir de uma tomada, basta ler ou recv-lo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top