Как использовать select и FD_SET в программировании сокетов?

Я новичок в программировании сокетов, и мне трудно понять, как работают select() и FD_SET().

Я модифицирую пример из учебника Биджа в попытке разобраться в этом. В цикле for я хочу сделать так: на каждой итерации я жду 4 секунды. Если чтение доступно, я бы вывел "A key was pressed", а если таймаут, то вывел бы "Timed out". Затем я очищаю набор и повторяю процесс еще 9 раз. Но похоже, что после установки файлового дескриптора 0 он никогда не снимается даже после вызова FD_ZERO() и/или FD_CLR(). Другими словами, после нажатия клавиши в первой итерации цикла дескриптор файла устанавливается на все остальные итерации и больше не ждет. Так что, должно быть, я что-то упускаю, но я не знаю что.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

#define SERVERPORT 4950

int main(int argc, char *argv[]) {
    struct sockaddr_in their_addr; // connector's address information
    struct hostent *he;
    int numbytes;
    int broadcast = 1;

    if ((he=gethostbyname(argv[1])) == NULL) {  // get the host info
        perror("gethostbyname");
        exit(1);
    }

    // this call is what allows broadcast packets to be sent:
    if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast,
        sizeof broadcast) == -1) {
        perror("setsockopt (SO_BROADCAST)");
        exit(1);
    }
    their_addr.sin_family = AF_INET;     // host byte order
    their_addr.sin_port = htons(SERVERPORT); // short, network byte order
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);

    struct timeval tv;
    fd_set broadcastfds;

    int i;
    for(i=0; i < 10; i++) {
        tv.tv_sec = 4;
        tv.tv_usec = 500000;

        FD_ZERO(&broadcastfds);
        FD_CLR(0, &broadcastfds);
        FD_SET(0, &broadcastfds);
        if(select(0+1, &broadcastfds, NULL, NULL, &tv) == -1) perror("select");

        if (FD_ISSET(0, &broadcastfds)) printf("A key was pressed!\n");
        else printf("Timed out.\n");
        fflush(stdout); 
    }   
    close(sockfd);
    return 0;
}
10
задан user1161604 6 February 2012 в 18:41
поделиться