UNP函数笔记四: I/O复用:select和poll函数

第六章  I/O复用:select和poll函数:

#include <sys/select.h>
#include <sys/time.h>
int select(int maxfdp1, fd_set * readset, fd_set * writeset, 
           fd_set * exceptset, const struct timeval * timeout);
    if timeout == NULL:
        wait forever
    else if timeout->tv_sec == 0 && timeout->tv_usec == 0:
        no wait
    else:
        wait to timeout
    success return ready-des-count, time out return 0, error return -1
    struct timeval {
        long  tv_sec;
        long  tv_usec;
    };

FD_SETSIZE

#include <sys/select.h>
void FD_ZERO(fd_set * fdset);
void FD_CLR(int fd, fd_set * fdset);
void FD_SET(int fd, fd_set * fdset);
int FD_ISSET(int fd, fd_set * fdset);

#include <sys/socket.h>
int shutdown(int sockfd, int howto);
    howto:
        SHUT_RD(0), SHUT_WR(1), SHUT_RDWR(2)
    success return 0, error return -1

#include <sys/select.h>
#include <signal.h>
#include <time.h>
int pselect(int maxfdp1, fd_set * readset, fd_set * writeset, 
            fd_set * exceptset, const struct timespec * timeout, 
            const sigset_t * sigmask); 
    when call pselect, signal-mask be atomic to set as sigmask,
    when return, signal-mask will be set back to it was
    success return ready-des-count, time out return 0, error return -1
    struct timespec {
        time_t  tv_sec;
        long    tv_nsec;
    };

#include <poll.h>
int poll(struct pollfd * fdarray, nfds_t nfds, int timeout);
    timeout == INFTIM: wait forever
    timeout == 0:  no wait
    timeout > 0:   wait for timeout (ms)
    success return ready-des-count, timeout return 0, error return -1
    struct pollfd {
        int    fd;       /* descriptor to check, or < 0 to ignore */
        short  events;   /* events of interest on fd */
        short  revents;  /* events that occurred on fd */
    };
    events:
        POLLIN,  POLLRDNORM, POLLRDBAND, POLLPRI  /* read */
        POLLOUT, POLLWRNORM, POLLWRBAND           /* write */
    revents:
        POLLIN,  POLLRDNORM, POLLRDBAND, POLLPRI  /* read */
        POLLOUT, POLLWRNORM, POLLWRBAND           /* write */
        POLLERR, POLLHUP, POLLNVAL                /* except */

示例:

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>

#include "myio.h"

#define max(a, b) ((a) >= (b) ? (a) : (b))

void 
str_cli(FILE * fp, int sockfd)
{
    int     n;
    int     maxfdp1;
    fd_set  rset;
    char    sendline[MAXLINE];
    char    recvline[MAXLINE];

    FD_ZERO(&rset);
    for ( ; ; ) {
        FD_SET(fileno(fp), &rset);
        FD_SET(sockfd, &rset);
        maxfdp1 = max(fileno(fp), sockfd) + 1;
        if (select(maxfdp1, &rset, NULL, NULL, NULL) == -1) {
            printf("select error: %s\n", strerror(errno));
            exit(1);
        }

        if (FD_ISSET(sockfd, &rset)) {  /* socket is readable */
            if ((n = readline(sockfd, recvline, MAXLINE)) < 0) {
                printf("readline error: %s\n", strerror(errno));
                exit(1);
            }
            else if (n == 0) {
                printf("str_cli: server terminated prematurely\n");
                exit(0);
            }
            
            if (fputs(recvline, stdout) == EOF) {
                printf("fputs error: %s\n", strerror(errno));
                exit(1);
            }
        }

        if (FD_ISSET(fileno(fp), &rset)) {  /* input is readable */
            if (fgets(sendline, MAXLINE, fp) == NULL) {
                return;  /* all done */
            }
            n = strlen(sendline);
            if (writen(sockfd, sendline, n) != n) {
                printf("writen error: %s\n", strerror(errno));
                exit(1);
            }
        }
    }
}

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/select.h>
#include <sys/socket.h>

#include "myio.h"

#define max(a, b) ((a) >= (b) ? (a) : (b))

void 
str_cli(FILE * fp, int sockfd)
{
    int     n;
    int     maxfdp1;
    int     stdineof;
    fd_set  rset;
    char    buf[MAXLINE];

    stdineof = 0;
    FD_ZERO(&rset);
    for ( ; ; ) {
        FD_SET(sockfd, &rset);
        if (stdineof == 0) {
            FD_SET(fileno(fp), &rset);
            maxfdp1 = max(fileno(fp), sockfd) + 1;
        }
        else {
            maxfdp1 = sockfd + 1;
        }

        if (select(maxfdp1, &rset, NULL, NULL, NULL) == -1) {
            printf("select error: %s\n", strerror(errno));
            exit(1);
        }

        if (FD_ISSET(sockfd, &rset)) {  /* socket is readable */
            if ((n = read(sockfd, buf, MAXLINE)) < 0) {
                printf("read error: %s\n", strerror(errno));
                exit(1);
            }
            else if (n == 0) {
                if (stdineof == 1) {
                    return;  /* normal termination */
                }
                else {
                    printf("str_cli: server terminated prematurely\n");
                }
            }

            if (write(fileno(stdout), buf, n) != n) {
                printf("fputs error: %s\n", strerror(errno));
                exit(1);
            }
        }

        if (FD_ISSET(fileno(fp), &rset)) {  /* input is readable */
            if ((n = read(fileno(fp), buf, MAXLINE)) < 0) {
                printf("fputs error: %s\n", strerror(errno));
                exit(1);
            }
            else if (n == 0) {
                stdineof = 1;
                if (shutdown(sockfd, SHUT_WR) == -1) {  /* send FIN */
                    printf("shutdown error: %s\n", strerror(errno));
                    exit(1);
                }
                FD_CLR(fileno(fp), &rset);
                continue;
            }

            if (writen(sockfd, buf, n) != n) {
                printf("writen error: %s\n", strerror(errno));
                exit(1);
            }
        }
    }
}

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/select.h>

#include "myio.h"

#define LISTENQ   1024
#define SERV_PORT 34567

int 
main(int argc, char * argv[])
{
    int                 i;
    int                 count;
    int                 maxfd;
    int                 listenfd;
    int                 connfd;
    int                 sockfd;
    int                 nready;
    int                 client[FD_SETSIZE];
    ssize_t             n;
    fd_set              rset;
    fd_set              allset;
    char                buf[MAXLINE];
    socklen_t           clilen;
    struct sockaddr_in  cliaddr;
    struct sockaddr_in  servaddr;

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket error: %s\n", strerror(errno));
        exit(1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        printf("bind error: %s\n", strerror(errno));
        exit(1);
    }

    if ((listen(listenfd, LISTENQ)) == -1) {
        printf("listen error: %s\n", strerror(errno));
        exit(1);
    }

    maxfd = listenfd;  /* initialize */
    count = 0;         /* in use count of client[] array */

    FD_ZERO(&allset);
    FD_SET(listenfd, &allset);

    for ( ; ; ) {
        rset = allset;  /* structure assignment */
        if ((nready = select(maxfd+1, &rset, NULL, NULL, NULL)) == -1) {
            printf("select error: %s\n", strerror(errno));
            exit(1);
        }

        if (FD_ISSET(listenfd, &rset)) {  /* new client connection */
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
            if (connfd < 0) {
                printf("accept error: %s\n", strerror(errno));
                exit(1);
            }

            if (count >= FD_SETSIZE) {
                printf("too many clients\n");
                exit(1);
            }
            client[count++] = connfd;  /* save descriptor */

            FD_SET(connfd, &allset);  /* add new descriptor to set */
            if (connfd > maxfd) {
                maxfd = connfd;  /* for select */
            }

            if (--nready <= 0) {
                continue;  /* no more readable descriptors */
            }
        }

        for (i = 0; i < count; ++i) {  /* check all clients for data */
            sockfd = client[i];
            if (FD_ISSET(sockfd, &rset)) {
                if ((n = read(sockfd, buf, MAXLINE)) < 0) {
                    printf("read error: %s\n", strerror(errno));
                    exit(1);
                }
                else if (n == 0) {  /* connection closed by client */
                    if (close(sockfd) == -1) {
                        printf("close error: %s\n", strerror(errno));
                        exit(1);
                    }
                    FD_CLR(sockfd, &allset);
                    if (--count > 0) {
                        client[i] = client[count];
                    }
                    --i;
                }
                else {
                    if (writen(sockfd, buf, n) != n) {
                        printf("writen error: %s\n", strerror(errno));
                        exit(1);
                    }
                }

                if (--nready <= 0) {
                    break;  /* no more readable descriptors */
                }
            }
        }
    }
}

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stropts.h>
#include <poll.h>

#include "myio.h"

#ifndef INFTIM
#define INFTIM    (-1)
#endif

#ifndef OPEN_MAX
#define OPEN_MAX  (1024)
#endif

#define LISTENQ   1024
#define SERV_PORT 34567

int 
main(int argc, char * argv[])
{
    int                  i;
    int                  size;
    int                  count;
    int                  listenfd;
    int                  connfd;
    int                  sockfd;
    int                  nready;
    ssize_t              n;
    char                 buf[MAXLINE];
    socklen_t            clilen;
    struct pollfd      * client;
    struct sockaddr_in   cliaddr;
    struct sockaddr_in   servaddr;

#ifdef _SC_OPEN_MAX
    size = sysconf(_SC_OPEN_MAX);
    if (size <= 0)
#endif
        size = OPEN_MAX;

    client = (struct pollfd *)malloc(sizeof(struct pollfd) * size);
    if (client == NULL) {
        printf("malloc error: %s\n", strerror(errno));
        exit(1);
    }

    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("socket error: %s\n", strerror(errno));
        free(client);
        exit(1);
    }

    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family      = AF_INET;
    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servaddr.sin_port        = htons(SERV_PORT);

    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1) {
        printf("bind error: %s\n", strerror(errno));
        free(client);
        exit(1);
    }

    if ((listen(listenfd, LISTENQ)) == -1) {
        printf("listen error: %s\n", strerror(errno));
        free(client);
        exit(1);
    }

    client[0].fd      = listenfd;
    client[0].events  = POLLRDNORM;
    client[0].revents = 0;  /* not need */
    count = 1;  /* in use count of client[] array */

    for ( ; ; ) {
        if ((nready = poll(client, count, INFTIM)) == -1) {
            printf("poll error: %s\n", strerror(errno));
            free(client);
            exit(1);
        }

        if (client[0].revents & POLLRDNORM) {  /* new client connection */
            clilen = sizeof(cliaddr);
            connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
            if (connfd < 0) {
                printf("accept error: %s\n", strerror(errno));
                free(client);
                exit(1);
            }

            if (count >= size) {
                printf("too many clients\n");
                free(client);
                exit(1);
            }
            client[count].fd      = connfd;
            client[count].events  = POLLRDNORM;
            client[count].revents = 0;  /* need this in next "for" */
            ++count;

            if (--nready <= 0) {
                continue;  /* no more readable descriptors */
            }
        }

        for (i = 1; i < count; ++i) {  /* check all clients for data */
            if (client[i].revents & (POLLRDNORM | POLLERR)) {
                sockfd = client[i].fd;
                if ((n = read(sockfd, buf, MAXLINE)) < 0) {
                    if (errno == ECONNRESET) {
                        /* connection reset by client */
                        if (close(sockfd) == -1) {
                            printf("close error: %s\n", strerror(errno));
                            free(client);
                            exit(1);
                        }
                        if (--count > 1) {
                            client[i] = client[count];
                        }
                        --i;
                    }
                    else {
                        printf("read error: %s\n", strerror(errno));
                        free(client);
                        exit(1);
                    }
                }
                else if (n == 0) {
                    /* connection closed by client */
                    if (close(sockfd) == -1) {
                        printf("close error: %s\n", strerror(errno));
                        free(client);
                        exit(1);
                    }
                    if (--count > 1) {
                        client[i] = client[count];
                    }
                    --i;
                }
                else {
                    if (writen(sockfd, buf, n) != n) {
                        printf("writen error: %s\n", strerror(errno));
                        free(client);
                        exit(1);
                    }
                }

                if (--nready <= 0) {
                    break;  /* no more readable descriptors */
                }
            }
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值