Epoll代码实例

来源:互联网 发布:新浪汽车销量数据库 编辑:程序博客网 时间:2024/05/23 12:20
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>#include <errno.h>#define MAXEVENTS 64static int set_non_block(int sockfd) {    int flags, s;    flags = fcntl(sockfd, F_GETFL, 0);    if (flags == -1) {        perror("fcntl");        return -1;    }    flags |= O_NONBLOCK;    s = fcntl(sockfd, F_SETFL, flags);    if (s == -1) {        perror("fcntl");        return -1;    }    return 0;}static void setreuseaddr(int sockfd) {    int opt = 1;    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(int)) < 0) {        perror("setsockopt(SO_REUSEADDR) failed");    }}static int create_and_bind(int port) {    struct sockaddr_in local, remote;    char buf[BUFSIZ];    int listenfd = -1;    //创建listen socket    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {        perror("sockfd\n");        exit(1);    }    set_non_block (listenfd);    setreuseaddr(listenfd);    bzero(&local, sizeof(local));    local.sin_family = AF_INET;    local.sin_addr.s_addr = htonl(INADDR_ANY);    local.sin_port = htons(port);    if (bind(listenfd, (struct sockaddr *) &local, sizeof(local)) < 0) {        perror("bind\n");        exit(1);    }    return listenfd;}int main(int argc, char *argv[]) {    int sockfd, s;    int efd;    struct epoll_event event;    struct epoll_event *events;    if (argc != 2) {        fprintf(stderr, "Usage: %s [port]\n", argv[0]);        exit(EXIT_FAILURE);    }    sockfd = create_and_bind(atoi(argv[1]));    if (sockfd == -1)        abort();    s = listen(sockfd, SOMAXCONN);    if (s == -1) {        perror("listen");        abort();    }    /**     * creates an epoll instance.     * On success, these system calls return a nonnegative file descriptor.     * On error, -1 is returned, and errno is set to indicate the error.     *     */    efd = epoll_create1(0);    if (efd == -1) {        perror("epoll_create");        abort();    }    event.data.fd = sockfd;    event.events = EPOLLIN | EPOLLET;    s = epoll_ctl(efd, EPOLL_CTL_ADD, sockfd, &event);    if (s == -1) {        perror("epoll_ctl");        abort();    }    /* Buffer where events are returned */    events = (struct epoll_event *) calloc(MAXEVENTS, sizeof(event));    /* The event loop */    while (1) {        int n, i;        /**/        n = epoll_wait(efd, events, MAXEVENTS, -1);        printf("n = %d\n", n);        for (i = 0; i < n; i++) {            if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP)                    || (!(events[i].events & EPOLLIN))) {                /* An error has occured on this fd, or the socket is not                 ready for reading (why were we notified then?) */                fprintf(stderr, "epoll error\n");                close(events[i].data.fd);                continue;            }            else if (sockfd == events[i].data.fd) {                printf("sockfd == events[i].data.fd\n");                /* We have a notification on the listening socket, which                 means one or more incoming connections. */                while (1) {                    struct sockaddr in_addr;                    socklen_t in_len;                    int infd;                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];                    in_len = sizeof in_addr;                    infd = accept(sockfd, &in_addr, &in_len);                    if (infd == -1) {                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {                            /* We have processed all incoming                             connections. */                            break;                        } else {                            perror("accept");                            break;                        }                    }                    s = getnameinfo(&in_addr, in_len, hbuf, sizeof hbuf, sbuf,                            sizeof sbuf,                            NI_NUMERICHOST | NI_NUMERICSERV);                    if (s == 0) {                        printf("Accepted connection on descriptor %d "                                "(host=%s, port=%s)\n", infd, hbuf, sbuf);                    }                    /* Make the incoming socket non-blocking and add it to the                     list of fds to monitor. */                    s = set_non_block(infd);                    if (s == -1)                        abort();                    event.data.fd = infd;                    event.events = EPOLLIN | EPOLLET;                    s = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);                    if (s == -1) {                        perror("epoll_ctl");                        abort();                    }                }                continue;            } else {                printf("readed fd = %d\n", events[i].data.fd);                /* We have data on the fd waiting to be read. Read and                 display it. We must read whatever data is available                 completely, as we are running in edge-triggered mode                 and won't get a notification again for the same                 data. */                int done = 0;                //                while (1) {                    ssize_t count;                    char buf[512];                    count = read(events[i].data.fd, buf, sizeof buf);                    printf("read %d bytes, fd = %d\n",count, events[i].data.fd);                    if (count == -1) {                        printf("read count %d, fd = %d, errno = %d\n",count, events[i].data.fd, errno);                        /* If errno == EAGAIN, that means we have read all                         data. So go back to the main loop. */                        if (errno != EAGAIN) {                            perror("read");                            done = 1;                        } else {                            //close(events[i].data.fd);                        }                        break;                    } else if (count == 0) {                        printf("read count 0, fd = %d\n", events[i].data.fd);                        /* End of file. The remote has closed the                         connection. */                        done = 1;                        break;                    }                    /* Write the buffer to standard output */                    s = write(1, buf, count);                    //fprintf(stdout,"%s",buf);                    //fflush(stdout);                    printf("write %d bytes, fd = %d\n",s, events[i].data.fd);//                    if (s == -1) {//                        perror("write");//                        abort();//                    }                }                if (done) {                    printf("Closed connection on descriptor %d\n",                            events[i].data.fd);                    /* Closing the descriptor will make epoll remove it                     from the set of descriptors which are monitored. */                    //close(events[i].data.fd);                }            }        }    }    free(events);    close(sockfd);    return EXIT_SUCCESS;}

0 0
原创粉丝点击