[TCP/IP] 多重化

Unixではselect関数を使用して、ペンディング中のI/Oをチェックするディスクリプタのリストを指定できる。
int select(int maxDescPlus1, fd_set *readDescs, fd_set *writeDescs, fd_set *exceptionDescs, struct timeval *timeout)

FD_ZERO(fd_set *descriptorVector) : fd_setにあるディスクリプタを全て削除
FD_CLR(int descriptor, fd_set *descriptorVector) : fd_setから削除
FD_SET(int descriptor, fd_set *descriptorVector) : 追加
FD_ISSET(int descriptor, fd_set *descriptorVector)

#include "TCPEchoServer.h"
#include <sys/time.h>
#include <fcntl.h>

int main(int argc, char *argv[]){
    int *servSock;
    int maxDescriptor;
    fd_set sockSet;
    long timout;
    struct timeval setTimeout;
    int running = 1;
    int noPorts;
    int port;
    unsigned short portNo;

    if(argc < 3) {
        fprintf(stderr, "Usage: %s <Timeout(secs.)><Port 1>... \n", argv[0]);
        exit(1);
    }

    timeout = atol(argv[1]);
    noPorts = argc - 2;

    servSock = (int *)malloc(noPorts * sizeof(int));

    maxDescriptor = -1;

    for (port = 0; port < noPorts; port++){
        portNo = atoi(argv[port + 2]);

        servSock[port] = CreateTCPServerSocket(portNo);

        if(servSock[port] > maxDescriptor)
            maxDescriptor = servSock[port];
    }

    printf("Starting server: Hit return to shutdown\n");
    while(running) {
        FD_ZERO(&sockSet);

        FD_SET(STDIN_FILENO, &sockSet);
        for(port = 0; port < noPorts; port++)
            FD_SET(servSock[port], &sockSet);

        setTimeout.tv_sec = timeout;
        setTimeout.tv_usec = 0;

        if(select(maxDescriptor + 1, &sockSet, NULL, NULL, &selTimout) == 0)
            printf("No echo request for %ld secs... Server still alive\n", timeout);
        else {
            if(FD_ISSET(STDIN_FILENO, &socket)){
                printf("Shutting down server\n");
                getchar();
                running = 0;
            }
            for (port = 0; port < noPorts; port++)
                if(FD_ISSET(servSock[port], &sockSet)){
                    printf("Request on port %d:", port);
                    HandleTCPClient(AcceptTCPConnection(servSock[port]));
                }
        }
    }
    for(port = 0; port < noPorts; port++)
        close(servSock[port]);

    free(servSock);
    exit(0);
}